How to use Pilog in PicoLisp

How to use Pilog in PicoLisp

Nov 9, 2021·

3 min read

In the last seven posts we introduced the main concepts and syntax of Pilog. However, all the queries were only done in interactive mode from the REPL. So how do we use it from PicoLisp?

Calling Pilog from Lisp and vice versa

The interface from PicoLisp to Pilog is via the functions goal (prepare a query from PicoLisp data) and prove (return an association list of successful bindings), and the application level functions pilog and solve. It is often used for database queries.

The opposite case - calling PicoLisp functions from Pilog - is done with the caret symbol ^ in the CAR of a Pilog clause and a PicoLisp programm body in the CDDR, and then unified with the result in the CADR. We will see now how this can look like.

Example: The factorial function

The factorial function of an integer Nis defined as N * N-1 * N-2 * ... * 1. Let's see how we can define it in Pilog. The factorial function can be implemented recursively (in this post we discussed the PicoLisp implementation).

The base case is for N=0. In this case, the result is 1. With this the calculation can stop, so we can use the cut operator T after this clause.

(be factorial (0 1) T)

For the other cases we can define it recursively. Let's state a rule (be factorial (@N @X) with three conditions:

  • bind @N-1 to @A,
  • call the factorial (recursion) of @A to bind @B to a value,
  • set @X as @N * @B.
(be factorial (@N @X)
   (^ @A (dec @N))
   (factorial @A @B)
   (^ @X (* @N @B)) )

(dec @N) and ( * @N @B) are PicoLisp functions.

We can call a PicoLisp function using a list with three ore more elements: The first element is the caret symbol ^, the second (CADR) is the variable, and the third (CDDR) is the program to be evaluated).

Let's test it in the REPL:

: (be factorial (0 1) T)
-> factorial

: (be factorial (@N @X)
      (^ @A (dec @N))
      (factorial @A @B)
      (^ @X (* @N @B)) )
-> factorial

: (? (factorial 5 @X))
-> NIL

It works!

Now let's use it from within PicoLisp. We can call Pilog predicates with the solve function:

(solve 'lst [. prg]) -> lst

Evaluates a Pilog query and, returns the list of result sets. If prg is given, it is executed for each result set, with all Pilog variables bound to their matching values, and returns a list of the results.

      (solve '((factorial 5 @X)) @X) ) )

Let's test it:

$ pil factorial.l

If we execute factorial.l, it prints 120.

You can find the factorial.l file here.

Next, we will look at a couple of pilog examples from the Rosetta Code:

After that we will introduce Pilog as query language for the PicoLisp database.