So I figured out how to fix this to do what I want.  Basically, the
CallLambda Userfunction needs to check that the first argument is a
RU.BINDING in addtion to RU.LAMBDA.  This this fix, things work as I
would like them to.  Nice addition - and powerful, too.

public class CallLambda implements Userfunction {

    private static final String NAME = "lcall";

    /** Get the name of the Jess function.
     * @see jess.Userfunction#getName()
     */
    public String getName() {
        return NAME;
    }

    /** Call the userfunction
     * @see jess.Userfunction#call(jess.ValueVector, jess.Context)
     */
    public Value call(ValueVector vv, Context context) throws
JessException {
        int narg = vv.size() - 1;
        // Check that we have at least one element.
        if (narg < 1)
            throw new JessException(NAME, "missing argument.", "");

        // Evluate a variable or a function call.
        Value valArg1 = vv.get(1);
        if (valArg1.type() == RU.VARIABLE || valArg1.type() ==
RU.FUNCALL) {
            valArg1 = valArg1.resolveValue(context);
        }

        // This must now be a lambda expression or a binding.
        if (valArg1.type() != RU.LAMBDA && valArg1.type() !=
RU.BINDING) {
            throw new JessException(
                                    NAME,
                                    "first argument is not a lambda
definition.",
                                    Integer.toString(valArg1.type()));
        }
        // Get the function value,...
        Deffunction d = (Deffunction) valArg1.functionValue(context);
        // ...construct the argument list and...
        ValueVector av = new ValueVector(narg);
        av.add(d.getName());
        for (int iArg = 2; iArg <= narg; iArg++) {
            av.add(vv.get(iArg));
        }
        // ...call and return the result.
        return d.call(av, context);
    }
}
On Aug 14, 2008, at 9:04 AM, Hal Hildebrand wrote:

Have tried using the CallLambda Userfunction class from

      http://herzberg.ca.sandia.gov/jesswiki/view?LambdaCallUserFunction

(load-function CallLambda)

(deftemplate functional-fact
    (slot func)
    )

(bind ?f (lambda (?x) (> 1 ?x)))

(assert (functional-fact (func ?f)))

(defrule test-me
    (functional-fact (func ?f))
    (test (lcall ?f 0))
    =>
    (printout t "1 > 0" crlf))

fails with:

Jess reported an error in routine lcall
      while executing (lcall ?f 0)
      while executing 'test' CE
      while executing rule LHS (TECT).
  Message: first argument is not a lambda definition. 4096.
  Program text: ( defrule test-me ( functional-fact ( func ?f ) )
( test ( lcall ?f 0 ) ) = > ( printout t "1 > 0" crlf ) )  at line 17.

Seems as though nothing I can do with the slot value will turn it
into a function call.

On Aug 14, 2008, at 8:23 AM, Hal Hildebrand wrote:

I would like to have functions contained in the slot value of a
fact and then apply them.  I can create and assign the function
values by using (lambda ...), which seems to be what I'm looking
for on that side of the equation:

(deftemplate functional-fact
    (slot func)
    )

(assert (functional-fact (func (lambda (?x) (> 1 ?x)))))

However, the question becomes how do I actually call this
function?  What I would like to do is use these in test CE:

(deftemplate functional-fact
    (slot func)
    )

(assert (functional-fact (func (lambda (?x) (> 1 ?x)))))

(defrule test-me
    (functional-fact (func ?function))
    (test (?function 0))
    =>
    (printout t "1 > 0" crlf))

However, this does not work as I would expect instead failing with:

Jess reported an error in routine call
     while executing (call ?function 0)
     while executing 'test' CE
     while executing rule LHS (TECT).
  Message: No method named '0' found in class jess.Deffunction.
  Program text: ( defrule test-me ( functional-fact ( func ?
function ) ) ( test ( ?function 0 ) ) = > ( printout t "1 > 0"
crlf ) )  at line 11.

Clearly, I'm not understanding this and would appreciate any help
from those on the list.

Thanks.



Reply via email to