Question

I have defined a boolean Jess function that accepts a lambda, as follows:

(deffunction at-least(?n ?lambda $?values)
    (>= (length$ (filter ?lambda ?values)) ?n))

Which I can call as follows:

(bind ?condition1 (at-least 1 (lambda (?arg) (= ?arg 0)) ?a ?b ?c))
(bind ?condition2 (at-least 2 (lambda (?arg) (< ?arg 0)) ?a ?b ?c))

This works just fine. But I use the same lambdas in many different places, so I'd like to make the code a little more concise by defining some functions for them:

(deffunction fn-zero()
    (lambda (?arg) (= ?arg 0)))

And call it like this:

(bind ?condition1 (at-least 1 (fn-zero) ?a ?b ?c))

This also works fine.

But once I want to add a parameter, I get an error message. I have this code:

(deffunction fn-less-than(?x)
    (lambda (?arg) (< ?arg ?x)))

(bind ?condition2 (at-least 1 (fn-less-than 0) ?a ?b ?c))

It throws the following exception:

jess.JessException: No such variable x

I can't figure out what I'm doing wrong here. Why does this work for a function without parameters, but not for one with parameters? More importantly: how can I make this work?

Was it helpful?

Solution

Jess lambdas aren't closures, so ?x isn't available when the function is executed. The way to fool with execution order in Jess is by evaluating strings; we want to hardcode the value of ?x into the function when it's returned, so we need to evaluate ?x when the function is being assembled. Something like this would work fine:

(deffunction fn-less-than(?x)
    (eval (str-cat "(lambda (?arg) (< ?arg " ?x "))")))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top