Hi,
This is mostly a copy/paste of Alexander's answer below in the form of a
short how to. I haven't seen such a one on the wiki, so may be it can
find its way there. However I'm too young here to take such a decision ;-)
==========
**How to access a Lisp function from Pilog**
Let's say that you have those two facts in a Pilog database:
(be age (Paul 19) )
(be age (Kate 17) )
and that you want to find the person under 18.
In full Prolog you may have written something like this:
underage(X) :- age(X,Y), Y < 18.
however in Pilog the following rule:
(be underage (@X)
(age @X @Y)
(< @Y 18) )
won't work and the query:
(? (underage @X) )
will yield to 'NIL' instead of the expected result '@X=Kate' .
The reason is that '<' (less than) is not Pilog function but only a Lisp
one in PicoLisp.
In order to embed a Lisp expression in a Pilog, you must use '^'
operator. It causes the rest of the expression to be taken as Lisp.
Then, inside the Lisp code you can in turn access Pilog-bindings with
the '->' function.
Hence, in our case the Prolog rule above translates as:
(be underage (@X)
(age @X @Y)
(^ @ (< (-> @Y) 18)) )
In '(^ @ (< (-> @Y) 18))', '@' is an anonymous variable used to get the
result. If you need to access the result you can bind it to a defined
variable like in '(^ @B (+ (-> @A) 7))' where '@B' is now bound to '@A + 7'.
You may prefer to define your own Pilog predicate in this particular
case. Let's say that to avoid confusion, you want to create a Pilog
predicate call 'less_than' to mimic the Lisp function '<':
(be less_than (@A @B)
(^ @ (< (-> @A) (-> @B) )))
Then the Pilog rule becomes:
(be underage_1 (@X)
(age @X @Y)
(less_than @Y 18) )
and now:
(? (underage @X) )
yields to:
@X=Kate
which is the expected result. Et voià!
==========
Best,
Eric
Le 12/11/2016 à 16:27, Alexander Burger a écrit :
Hi Eric,
(be underage (@X)
(age @X @Y)
(< @Y 18))
'<' is a Lisp function and not a Pilog rule. To embed a Lisp expression
in Pilog, you must use the '^' operator. It causes the rest of the
expression to be taken as Lisp, and inside the Lisp code you can in turn
access Pilog-bindings with the '->' function.
In the case above it should be something like
(^ @ (< (-> @Y) 18))
'@' is an anonymous variable here. If you want to bind the result of the
Lisp expression to a specific variable, it would be e.g.
(^ @X (+ (-> @N) 7))
This binds @X to @N + 7.
Of course, if you need '<' more often, you could define your own
predicate:
: (be < (@A @B)
(^ @ (< (-> @A) (-> @B))) )
-> <
: (? (< 3 4))
-> T
: (? (< 4 2))
-> NIL
♪♫ Alex
--
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe