The special forms in this section allow a Lisp expression to be evaluated, and the value used in Algernon in various ways. Before an expression is evaluated in Lisp, any Algernon variables appearing in the expression are replaced by their bindings.
Evaluates expression as a Lisp expression for side effects. Returned value is ignored. Thus one can print out the children of Tom using the path:
((child Tom ?x) (:lisp (format t "A child of Tom is ~a.~%" '?x))).
:eval is a synonym for :lisp.
Applies function to the values obtained by evaluating exp ... exp . Each of the exp may be of one of four forms:
When :funcall appears as a top-level special form in a path, the value returned is ignored by Algernon. However, :funcall can also be embedded in :bind or :branch forms, in which case the value returned can be bound to Algernon variables.
After substituting in the values of any Algernon variables, evaluate the second argument and unify the result with the first argument. The expression may be a Lisp expression or an embedded :funcall expression. For example, to determine the number of values in a slot: (:bind ?n (:funcall #'length (:values frame slot)))
Because the variable argument is unified with the result of evaluating expression, :bind can be used to bind multiple variables, destructure complex values, or test properties of the value returned. For example, suppose the Lisp function (gossip) returns a list of the form (Tom loves Mary) or (Bill hates Joe) or some such. We could select for a particular case, and bind variables to the names of the protagonists with: (:bind (?subj loves ?obj) (gossip))
The value returned from the Lisp function is captured using multiple-value-bind, with the second argument being the set of assumptions. This means that a Lisp function can store information in an external datastructure, indexed under the appropriate assumptions, using rules something like the following:
((R ?x ?y) -> (:funcall #'Fout '?x '?y :assumptions)) ((R ?x ?y) <- (:bind ?y (:funcall #'Fin '?x :assumptions)))
(There is still a problem with this, since the returned values will be cached in the slot, which may not be what we want.)
:branch works just like :bind, except that the result of evaluating expression is assumed to be a list of values, and variable is unified against each of those values along a separate branch.