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

Reply via email to