Variables, Symbols, Strings

(define x (list + '+ "+"))
x ==> (#[procedure +] + "+")
((car x) 2 3) ==> 5
(eq? (second x) '+) ==> #T
(eq? (third x) "+") ==> #F
(eq? (third x) '+) ==> #F

Abstract Syntax

(define (make-binop op left right)
  (list left op right))
(define (binop? expression) (pair? expression))
(define (binop.left binop) (first binop))
(define (binop.op binop) (second binop))
(define (binop.right binop) (third binop))

(make-binop '+ 5 10) ==> ?????

Concrete Expressions

(make-binop '+ 5 10)
        ; ==> (5 + 10)
(make-binop '* (make-binop '+ 3 7) 5))
        ; ==> ((3 + 7) * 5)
(make-binop '+ 'x 10))
        ; ==> (x + 10)
(make-binop '* (make-binop '+ 'x 7) 'y))
        ; ==> ((x + 7) * y)

Evaluating Expressions

(define (expression expr)
  (cond ((number? expr) expr)
        ((symbol? expr) (variable.value expr))
        ((binop? expr)
         (let ((op (binop.op expr))
               (rand-1 (expression 
                         (binop.left expr)))
               (rand-2 (expression
                         (binop.right expr))))
           (cond ((eq? op '+)
                  (+ rand-1 rand-2))
                 ((eq? op '*)
                  (* rand-1 rand-2))
                 (else (error "Bad operator"
                              expr)))))
        (else (error "Bad expression" expr))))

Abstract Syntax

;; Previous, "Infix" version
(define (make-binop op left right)
  (list left op right))
(define (binop? expression) (pair? expression))
(define (binop.left binop) (first binop))
(define (binop.op binop) (second binop))
(define (binop.right binop) (third binop))

;; New, "Prefix" version
(define (make-binop op left right)
  (list op left right))
(define (binop? expression) (pair? expression))
(define (binop.left binop) (second binop))
(define (binop.op binop) (first binop))
(define (binop.right binop) (third binop))

(make-binop '+ 5 10)) ==> ????

Variables and Lookup

   (define (assq name a-list)
     ;; A-List looks like
     ;;   ((name1 ...) (name2 ...) ...)
     (cond ((null? a-list) #F)
           ((eq? name (first (car a-list)))
            (car a-list))
           (else (assq name (cdr a-list)))))

   (define (variable.value name)
     (let ((entry (assq name variables)))
       (if entry
           (cdr entry)
           (error "No such variable" name))))

List of Operators

(define (expression expr)
  (define operators
    (list (cons '+ +)
          (cons '* *)))
  (cond ...
    ((binop? expr)
     (let ((op (binop.op expr)) ...)
       (let ((procedure (assq op operators)))
         (if procedure
             ((cdr procedure) rand-1 rand-2)
             (error "Bad operator" expr)))))
    ...))

Are Operators Just Variables?

(define variables
  (list (cons 'X 3)
        (cons 'Y 5)
        (cons '+ +)
        (cons '* *)))

(define (expression expr)
  (cond ...
        ((binop? expr)
         (let ((op (binop.op expr)) ...)
           (let ((procedure (variable.value op)))
             (procedure rand-1 rand-2))))
        ...))

Data Abstraction: Bane or Boon?

(define make-var cons)
(define var.name car)
(define var.value cdr)

(define (variable.value var)
  (define (loop vars)
    (if (null? vars)
        (error "Undefined variable" var)
        (let ((first-var (first vars)))
          (if (eq? var (var.name first-var))
              (var.value first-var)
              (loop (cdr vars))))))
  (loop variables))

(define (variable.value name)
  (let ((entry (assq name variables)))
    (if entry
        (cdr entry)
        (error "No such variable" name))))