(define title "equal?") (define description "") ;; ========================================================= ;; An ATOM is one of: (1) Symbol (2) String (3) Number ;; AKA: Atom = Symbol | String | Number ;; Anything -> Boolean (define (atom? x) (or (symbol? x) (string? x) (number? x))) ;; Anything -> Boolean (define (mota? x) (not (atom? x))) ;; Atom Atom -> Boolean (define (atom=? x y) (cond [(and (symbol? x) (symbol? y)) (symbol=? x y)] [(and (string? x) (string? y)) (string=? x y)] [(and (number? x) (number? y)) (= x y)] [else false])) ;; ========================================================= ;; An SEXP (S-expression) is one of: ;; -- empty ;; -- (cons Atom SEXP) ;; -- (cons SEXP SEXP) ;; What's a sexp good for? Who cares? ;; ekwal? : SEXP SEXP -> Boolean ;; are the two given SEXPs equal? ;; Examples: ;; same item w/list & cons ;; empty (cons empty empty) ;; Write EKWAL? for faux quiz. ;; Programmers are not to be measured ;; by their ingenuity and their logic ;; but by the completeness of their case analysis ;; TEMPLATE -- via 2-dimensional template #; (define (ekwal? s t) (cond ;; first set of cases: [(and (empty? s) (empty? t)) ...] [(and (empty? s) (atom? (first t))) ... (first t) ... (rest t) ...] [(and (empty? s) (mota? (first t))) ... (rest t) ...] ;; second set of cases: [(and (atom? (first s)) (empty? t)) ... ] [(and (atom? (first s)) (atom? (first t))) ... (first s) ... (rest s) ... (first t) ... (rest t)] [(and (atom? (first s)) (mota? (first t))) ...] ;; third set of cases: [(and (cons? s) (empty? t)) ...] [(and (cons? s) (atom? (first t))) ...] [(and (cons? s) (mota? (first t))) ... (first s) ... (rest s) ... (first t) ... (rest t)])) (define (ekwal? s t) (cond ;; first set of cases: [(and (empty? s) (empty? t)) true] [(and (empty? s) (atom? (first t))) false] [(and (empty? s) (mota? (first t))) false] ;; second set of cases: [(and (atom? (first s)) (empty? t)) false ] [(and (atom? (first s)) (atom? (first t))) (and (atom=? (first s) (first t)) (ekwal? (rest t) (rest t)))] [(and (atom? (first s)) (mota? (first t))) false] ;; third set of cases: [(and (mota? (first s)) (empty? t)) false] [(and (mota? (first s)) (atom? (first t))) false] [(and (mota? (first s)) (mota? (first t))) (and (ekwal? (first s) (first t)) (ekwal? (rest s) (rest t)))])) ;; develop examples: as tests (ekwal? (list (list 'a) empty) (list (list 'a) empty)) (equal? (ekwal? empty empty) true) (equal? (ekwal? empty (list (list 'a))) false) (equal? (ekwal? empty (list 'a)) false) (equal? (ekwal? (list 'a) empty) false) (equal? (ekwal? (list 'a) (list (list 'a))) false) (equal? (ekwal? (list 'a) (list "a")) false) (equal? (ekwal? (list (list 'a) empty) empty) false) (equal? (ekwal? (list (list 'a) empty) (list (list 'b) empty)) false) (equal? (ekwal? (list (list 'a) empty) (list 'b empty)) false) ;; =========================================================== ;; AE is one of: ;; -- number ;; -- (make-add AE AE) ;; -- (make-mul AE AE) (define-struct add (left right)) (define-struct mul (left right)) ;; examples: 10 (make-add 10 20) (make-mul (make-add 10 20) 3) ;; what's a good interpretation for these things: ;; number is a number ;; (make-add 10 20) stands for (+ 10 20) ;; (make-mul 10 20) stands for (* 10 20) ;; if that's so, what would be the value of: 10 "should be" 10 (make-add 10 20) "should be" 30 (make-mul (make-add 10 20) 3) "should be" 90 ;; AE -> Number ;; what would this AE evaluate to if DrScheme got a hold of ;; its interpretation? (define (evaluate a) (cond [(number? a) a] [(add? a) (+ (evaluate (add-left a)) (evaluate (add-right a)))] [(mul? a) (* (evaluate (mul-left a)) (evaluate (mul-right a)))])) (equal? (evaluate 10) 10) (equal? (evaluate (make-add 10 20)) 30) (equal? (evaluate (make-mul (make-add 10 20) 3)) 90)