next up previous contents index
Next: Interacting with the User Up: Special Forms Previous: Calling Algernon from Lisp

Calling Lisp from Algernon

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.

(:lisp  expression)

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  expression)

:eval is a synonym for :lisp.

(:test  expression)
Evaluates expression as a Lisp expression and succeeds iff it does not evaluate to nil.

(:funcall  function exp tex2html_wrap_inline1672 ...exp tex2html_wrap_inline1674 )

Applies function to the values obtained by evaluating exp tex2html_wrap_inline1672 ... exp tex2html_wrap_inline1674 . Each of the exp tex2html_wrap_inline1680 may be of one of four forms:

:assumptions  -- returns the list of lists of assumptions currently in force, in case the Lisp function needs them for something.
(:values  frame slot) -- evaluates to a list of the values stored in slot of frame, stripped of the associated assumptions.
(:non-values  frame slot) -- evaluates to a list of the explicit non-values in slot of frame, stripped of their associated assumptions.
otherwise -- evaluated as a Lisp expression.

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.

(:bind  variable expression)
(:bind (variable tex2html_wrap_inline1480 ) expression)

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  variable expression)

: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.


next up previous contents index
Next: Interacting with the User Up: Special Forms Previous: Calling Algernon from Lisp

Micheal S. Hewett
Tue Oct 29 11:15:33 CST 1996