Re: JESS: Calling a function on all elements in a list

2008-03-10 Thread Ernest Friedman-Hill


Actually, something much like Wolfgang's "apply$" is already built
into recent versions of Jess; it's called "map". But I actually don't
think that's what the O.P. is after: rather than calling a function
with each element of a list as successive arguments, I think he wants
to call the function on all the arguments in a list at once. In Lisp
this function is called "reduce", and although it currently doesn't
appear in Jess (it should, soon) I do have the code for an
implementation of reduce by Win Carus of Information Extraction
Systems, Inc. You can compile this, load it using load-function, and
use it as shown in the examples below.


/** ReduceMF
*
* Function to reduce a list of multifields to a single value.
* (reduce  +)
* For example:
*
* (reduce 0 + (create$ 1 2 3 4)) => 10
* (reduce "" str-cat (create$ "this" "that" "those")) => "thisthatthose"
* (reduce 0 (lambda (?n ?m ?o) (+ ?n (/ ?m ?o))) (create$ 1 2 3)
(create$ 4 5 6)
) => 1.15
*
* 
* (C) 2007 Information Extraction Systems, Inc.
*/
class ReduceMF implements Userfunction, Serializable {
   /** Get the name of the jess function
* @see jess.Userfunction#getName()
*/
   public String getName() {
   return "reduce";
   }

   /** Call the userfunction
* @see jess.Userfunction#call(jess.ValueVector, jess.Context)
 */   public Value call(ValueVector vv, Context context)
throws JessExce
ption {
   Value tmpValue = vv.get(1).resolveValue(context);
   Userfunction function = vv.get(2).functionValue(context);
  if (vv.size() > 3) {

   ValueVector args = new ValueVector();
   args.add(new Value("lambda", RU.SYMBOL));
   for (int i = 0; i < vv.size()-2; ++i)
   args.add(Funcall.NIL);

   for (int i = 0; i < (vv.get(3).listValue(context)).size
(); ++i) {
   args.set(tmpValue, 1);
   for (int j = 3; j < vv.size(); j++) {
args.set((vv.get(j).listValue(context)).get(i),
j-1);
   }
   tmpValue = function.call(args, context);
   }
   }
   return tmpValue;
   }
}


On Mar 10, 2008, at 3:36 AM, Wolfgang Laun wrote:


Why do you want to avoid foreach which happens to cater
for your needs? Just write a simple wrapper (I'll call
it apply$) and use it just like (apply):

; a function to be called on each element of a list
(deffunction show (?x)
   (printout t "show: " ?x crlf)
)

; (apply$  *)
; calls 1st argument for each successive argument,
; flattening list arguments
(deffunction apply$ (?func $?list)
   (foreach ?el $?list (apply ?func ?el))
)

; example for calling apply$
(bind ?alist (create$ foo bar blech))
(apply$ show ?alist)

Regards
Wolfgang


JKBM wrote:


I was wondering if there was any way to call a function on a variable
containing a list without having to use a foreach/while loop.
(apply + 1 2
3) obviously works, but (apply + (create$ 1 2 3)) doesn't, so that
doesn't
help me.  This sort of problem comes up a lot, and I usually
handle it by
implode$-ing the list, str-cat-ing the function and parentheses,
and then
build-ing it as follows:


(bind ?list (create$ 1 2 3))

(apply + ?bind) ;ERROR, as mentioned above
(build (str-cat "(+ " (implode$ ?list) ")) ;SUCCESS


However, this time, I'm dealing with a list of fact-ids, and this
method
doesn't work because Jess doesn't parse "" to a fact-id
from the
implode$-ed string.  I thought maybe I could create$ a new list
with the
function at the beginning, but there is no way that I could find
to evaluate
a list, only a string.  E.g.:

(bind ?list (create$ 1 2 3))

(bind ?flist (create$ + ?list)) ;?flist is (+ 1 2 3), but can't
evaluate


So, I guess I'm looking for three possible solutions:
1) calling a function on a list
2) getting Jess to correctly parse a fact-id from a string
3) getting Jess to evaluate a list as a function

Any ideas?  Or should I just give up and resort to iterative
measures?
--
View this message in context: http://www.nabble.com/Calling-a-
function-on-all-elements-in-a-list-tp15921074p15921074.html
Sent from the Jess mailing list archive at Nabble.com.



To unsubscribe, send the words 'unsubscribe jess-users
[EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the list
(use your own address!) List problems? Notify owner-jess-
[EMAIL PROTECTED]








To unsubscribe, send the words 'unsubscribe jess-users
[EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the list
(use your own address!) List problems? Notify owner-jess-
[EMAIL PROTECTED]



-
Ernest Friedman-Hill
Informatics & Decision

Re: JESS: Calling a function on all elements in a list

2008-03-10 Thread Wolfgang Laun

Why do you want to avoid foreach which happens to cater
for your needs? Just write a simple wrapper (I'll call
it apply$) and use it just like (apply):

; a function to be called on each element of a list
(deffunction show (?x)
  (printout t "show: " ?x crlf)
)

; (apply$  *)
; calls 1st argument for each successive argument,
; flattening list arguments
(deffunction apply$ (?func $?list)
  (foreach ?el $?list (apply ?func ?el))
)

; example for calling apply$
(bind ?alist (create$ foo bar blech))
(apply$ show ?alist)

Regards
Wolfgang


JKBM wrote:


I was wondering if there was any way to call a function on a variable
containing a list without having to use a foreach/while loop.  (apply + 1 2
3) obviously works, but (apply + (create$ 1 2 3)) doesn't, so that doesn't
help me.  This sort of problem comes up a lot, and I usually handle it by
implode$-ing the list, str-cat-ing the function and parentheses, and then
build-ing it as follows:


(bind ?list (create$ 1 2 3))

(apply + ?bind) ;ERROR, as mentioned above
(build (str-cat "(+ " (implode$ ?list) ")) ;SUCCESS


However, this time, I'm dealing with a list of fact-ids, and this method
doesn't work because Jess doesn't parse "" to a fact-id from the
implode$-ed string.  I thought maybe I could create$ a new list with the
function at the beginning, but there is no way that I could find to evaluate
a list, only a string.  E.g.:

(bind ?list (create$ 1 2 3))

(bind ?flist (create$ + ?list)) ;?flist is (+ 1 2 3), but can't evaluate


So, I guess I'm looking for three possible solutions:
1) calling a function on a list
2) getting Jess to correctly parse a fact-id from a string
3) getting Jess to evaluate a list as a function

Any ideas?  Or should I just give up and resort to iterative measures?
--
View this message in context: 
http://www.nabble.com/Calling-a-function-on-all-elements-in-a-list-tp15921074p15921074.html
Sent from the Jess mailing list archive at Nabble.com.



To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the list
(use your own address!) List problems? Notify [EMAIL PROTECTED]








To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the list
(use your own address!) List problems? Notify [EMAIL PROTECTED]




JESS: Calling a function on all elements in a list

2008-03-08 Thread JKBM

I was wondering if there was any way to call a function on a variable
containing a list without having to use a foreach/while loop.  (apply + 1 2
3) obviously works, but (apply + (create$ 1 2 3)) doesn't, so that doesn't
help me.  This sort of problem comes up a lot, and I usually handle it by
implode$-ing the list, str-cat-ing the function and parentheses, and then
build-ing it as follows:


(bind ?list (create$ 1 2 3))

(apply + ?bind) ;ERROR, as mentioned above
(build (str-cat "(+ " (implode$ ?list) ")) ;SUCCESS


However, this time, I'm dealing with a list of fact-ids, and this method
doesn't work because Jess doesn't parse "" to a fact-id from the
implode$-ed string.  I thought maybe I could create$ a new list with the
function at the beginning, but there is no way that I could find to evaluate
a list, only a string.  E.g.:

(bind ?list (create$ 1 2 3))

(bind ?flist (create$ + ?list)) ;?flist is (+ 1 2 3), but can't evaluate


So, I guess I'm looking for three possible solutions:
1) calling a function on a list
2) getting Jess to correctly parse a fact-id from a string
3) getting Jess to evaluate a list as a function

Any ideas?  Or should I just give up and resort to iterative measures?
--
View this message in context: 
http://www.nabble.com/Calling-a-function-on-all-elements-in-a-list-tp15921074p15921074.html
Sent from the Jess mailing list archive at Nabble.com.



To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the list
(use your own address!) List problems? Notify [EMAIL PROTECTED]