next up previous contents
Next: Returning Values from Lisp Up: Calling Lisp and the Previous: Calling Lisp and the

Evaluating Lisp Expressions

tabular542

The special forms :eval and :test take a Lisp expression including Algernon variables, substitute any bindings available for the Algernon variables, and evaluate the expression in Lisp.

We have already seen the :test special form used in the rule

displaymath1339

to test whether the value bound to the variable ?t satisfies a numerical relation.

For this and several following examples, we will use a small family tree and a few properties of people.

  (tell '((:taxonomy (physical-objects
                      (people Adam Beth Charles Donna Ellen)))))
  
  (tell '((:slot child    (people people))
          (:slot happy    (people booleans) :cardinality 1)
          (:slot friendly (people booleans) :cardinality 1)
          (:slot age      (people :number)  :cardinality 1)))

  (tell '((child Adam Charles)
          (child Adam Donna)
          (child Adam Ellen)))

After asserting this information, we use the Algernon interface to inspect the contents of the frame describing Adam:

algy> vf adam
Adam: 
  Name:       (adam)
  Isa:        objects physical-objects people things
  Child:      ellen donna charles

The following query looks up Adam's children and prints their names.

  (ask '((child Adam ?kid)
         (:eval (format t "~%Adam has a child named ~a." '?kid)))
       :comment "Print names of all three children")

On querying the first predicate, (child Adam ?kid), the path will branch three ways, one binding the variable ?kid to each child. Along each branch, the :eval special form will evaluate the format expression to print a line. Notice that '?kid is quoted in the format expression. This is because the binding for the Algernon variable ?kid is substituted into the expression before Lisp evaluates it. Since that binding is an Algernon frame, it will give an error if it is evaluated as a Lisp symbol, so it must be quoted.

QUERYING:  Print names of all three children

Adam has a child named ELLEN.
Adam has a child named DONNA.
Adam has a child named CHARLES.

 Result (1 of 3):
   Binding:             ?kid   --- ellen "[ellen]"
                       
 Result (2 of 3):
   Binding:             ?kid   --- donna "[donna]"
                       
 Result (3 of 3):
   Binding:             ?kid   --- charles "[charles]"
                       
  => T

Now let's query the user (via the Lisp function y-or-n-p) to find out whether he or she likes each child, and assert that the child is happy if so.

  (tell '((child Adam ?kid)
          (:test (y-or-n-p "Do you like ~a?" '?kid))
          (:eval (format t "  ~a is happy!" '?kid))
          (happy ?kid true))
        :comment "Check whether each kid is liked by user.")

This path is asserted rather than queried because we want to assert (happy ?kid true) if the previous forms succeed, rather than checking whether it is currently known.

In this case, the user likes Ellen and Charles, but not Donna. Two paths from the three-way branch on (child Adam ?kid) succeed, while the other fails at the :test. Notice that the order in which the questions are asked and results are printed demonstrates that branches of the same path are followed in parallel.

ASSERTING:   Check whether each kid is liked by user.
Do you like ELLEN? (Y or N): y
Do you like DONNA? (Y or N): n
Do you like CHARLES? (Y or N): y
  ELLEN is happy!  CHARLES is happy!

 Result (1 of 2):
   Binding:             ?kid   --- ellen "[ellen]"
                       
 Result (2 of 2):
   Binding:             ?kid   --- charles "[charles]"
                       
  => T

After this interaction, we view the three frames and verify that, indeed, Ellen and Charles are now known to be happy. Although we could not infer that Donna is happy, we don't know that she is unhappy.

algy> vf ellen
Ellen: 
  Name:       (ellen)
  Isa:        objects physical-objects people things
  Happy:      true

algy> vf donna
Donna: 
  Name:       (donna)
  Isa:        objects physical-objects people things

algy> vf charles
Charles: 
  Name:       (charles)
  Isa:        objects physical-objects people things
  Happy:      true

This illustrates an important principle of user-interface design: the user must always have a way to refuse to answer. In this case, we satisfied this requirement by interpreting a ``No'' answer to y-or-n-p as providing no information.


next up previous contents
Next: Returning Values from Lisp Up: Calling Lisp and the Previous: Calling Lisp and the

Micheal S. Hewett
Tue Oct 29 10:54:13 CST 1996