[   ^ to index...   |   <-- previous   |   next -->   ]

Programs as data

The idea that programs are lists makes Lisp well-suited to meta-programming---programs that modify other programs. For this reason, Lisp dialects are popular among AI researchers.

Here are some simple examples of programs as data: to prevent evaluation of any expression, you can simply put a single quote in front of the expression:

; Evaluate list data as if it were an expression in the-environment
(eval (list '+ 1 2 3) (the-environment))

; A single quote recursively prevents evaluation of sublists 
(define mystuff '(* (+ 1 2) 3))

A simple constraint solver

The following code implements a simple constraint solver. A constraint solver is a program to which you can feed constraints on variables---and the solver will compute all satisfying assignments of values within some domain.

; Replaces all occurrences in alist of sym with replacement.
(define (replace-sym sym replacement alist)
  (if (null? alist) 
     ()
      (let* ((current (car alist))
             (replaced-current
              (cond ((symbol? current)
                        (if (eq? sym current) replacement current))
                    ((list? current)
                        (replace-sym sym replacement current))
                    (else current))))
        (cons replaced-current (replace-sym sym replacement (cdr alist))))))

; A function that replaces varname with each of nums, then evaluates
; the constraint under that substitution.  All satisfying numbers are
; returned as a list
(define (try-nums varname nums constraint)
  (if (null? nums)
      ()
      (let* ((num  (car nums))
             (rest (cdr nums))
             (rest-result (try-nums varname rest constraint))
             (substituted (replace-sym varname num constraint)))
        (if (eval substituted (the-environment))
            (cons num rest-result)
            rest-result))))
            
(define my-constraint '(and (> x 3) (< x 9) (> (/ x 2) (- x 4))))
(define digits '(0 1 2 3 4 5 6 7 8 9))
(try-nums 'x digits my-constraint)

The last line prints (4 5 6 7), which are all values which satisfy my-constraint with respect to x. Notice that we did not have to write code explicitly to evaluate this constraint---instead, we replace the variable with the value, using replace-sym, and use the eval function.

Note: I don't necessarily expect you to understand this code. I had some empty space on my handouts, so I filled it; some of you may have fun figuring this program out.


Keunwoo Lee
Last modified: Wed May 2 20:38:36 PDT 2001