#lang racket ;; CSE341 Fall 2011, structs, interpreters, etc. ;; suppose we wanted a "one-of type" using nothing but lists and ;; symbols and such, like ML's ;; datatype exp = Const of int | Add of exp * exp | Negate of exp (define (Const i) (list 'Const i)) (define (Add e1 e2) (list 'Add e1 e2)) (define (Negate e) (list 'Negate e)) ;; these work for "any exp" (just in our heads), but not other things (define (Const? x) (eq? (car x) 'Const)) (define (Add? x) (eq? (car x) 'Add)) (define (Negate? x) (eq? (car x) 'Negate)) (define Const-int cadr) (define Add-e1 cadr) (define Add-e2 caddr) (define Negate-e cadr) ;; take any expression return a Const (define (eval-exp e) (cond [(Const? e) e] [(Add? e) (let ([v1 (Const-int (eval-exp (Add-e1 e)))] [v2 (Const-int (eval-exp (Add-e2 e)))]) (Const (+ v1 v2)))] [(Negate? e) (Const (- 0 (Const-int (eval-exp (Negate-e e)))))] [#t (error "eval-exp expected an exp")])) (define (test1) (eval-exp (Negate (Add (Const 2) (Const 2))))) ;; much more convenient is struct ; (for any conceptual record or datatype) (struct const (int) #:transparent) (struct add (e1 e2) #:transparent) (struct negate (e) #:transparent) (define (eval-exp2 e) (cond [(const? e) e] [(add? e) (let ([v1 (const-int (eval-exp2 (add-e1 e)))] [v2 (const-int (eval-exp2 (add-e2 e)))]) (const (+ v1 v2)))] [(negate? e) (const (- 0 (const-int (eval-exp2 (negate-e e)))))] [#t (error "eval-exp2 expected an exp")])) (define (test2) (eval-exp2 (negate (add (const 2) (const 2))))) ;; but it's much more than convenience: ;; the result of add is _not_ a list ;; (every type predicate except add? returns #f) ;; a little digression on eval (define (make-some-code y) (if y (list 'begin (list 'print "hi") (list '+ 4 2)) (list '+ 5 3))) (define (prog x) (eval (make-some-code x))) (define (make-some-code2 y) (if y (quote (begin (print "hi") (+ 4 2))) (quote (+ 5 3)))) ;; a "macro" for our arithmetic language via a Racket function (define (triple x) ; produce arith-exp that when interpreted triples (add x (add x x))) (define arith-exp-example (negate (triple (negate (const 4))))) (define the-answer (eval-exp2 arith-exp-example))