ANSI Common Lisp入門? lispの世界へようこそ 練習問題1
http://d.hatena.ne.jp/sDaigo/comment?date=20100325#c
lisp難しいです><。分からないのでschemeで回答します。
以下の式が評価された時何が起こるか説明せよ
(+ (- 5 1) (+ 3 7)) (list 1 (+ 2 3)) (if (listp 1) (+ 1 2) (+ 3 4)) (list (and (listp 3) t) (+ 1 2))
これは評価器を作る問題なんですね。わかります><。
;;内部のeval,applyを使って手抜き ;;; util (define (eval: exp) ;;代入がないのでenvはいらない (cond ((self-evaluate? exp) (t-eval exp)) ((if? exp) (apply eval-if (cdr exp))) ((and? exp) (eval-and (cdr exp))) (else (apply (eval: (car exp)) (map eval: (cdr exp)))))) (define self-evaluate? (complement pair?)) (define t-eval (cut eval <> (interaction-environment))) (define (dispatch x) (compose (pa$ eq? x) car)) (define if? (dispatch 'if)) (define (eval-if p true-clause false-clause) (if (eval: p) (eval: true-clause) (eval: false-clause))) (define and? (dispatch 'and)) (define (eval-and xs) (match xs [(x) (eval: x)] [(x . xr) (if (eval: x) (eval-and xr) #f)])) (define (trace$ fn) ;;多値とか無視 (lambda (x) (print "input: " x) (rlet1 rv (fn x) (print "output: " rv)))) (set! eval: (trace$ eval:))
問題に回答
これでinputとoutputがどうなっているかを説明すればいいんですね。
遅延評価とかかかれていないので評価規則はどのようになっているんでしょう?
(今回の回答では関数もsymbolから取り出しつつ左から右の作用的順序で評価してます><*1。)
(define listp list?) ;;CLとの互換性のため (define t #t) (eval: '(+ (- 5 1) (+ 3 7))) (print "==") (eval: '(list 1 (+ 2 3))) (print "==") (eval: '(if (listp 1) (+ 1 2) (+ 3 4))) (print "==") (eval: '(list (and (listp 3) t) (+ 1 2)))
結果
input: (+ (- 5 1) (+ 3 7)) input: + output: #<subr +> input: (- 5 1) input: - output: #<subr -> input: 5 output: 5 input: 1 output: 1 output: 4 input: (+ 3 7) input: + output: #<subr +> input: 3 output: 3 input: 7 output: 7 output: 10 output: 14 == input: (list 1 (+ 2 3)) input: list output: #<subr list> input: 1 output: 1 input: (+ 2 3) input: + output: #<subr +> input: 2 output: 2 input: 3 output: 3 output: 5 output: (1 5) == input: (if (listp 1) (+ 1 2) (+ 3 4)) input: (listp 1) input: listp output: #<subr list?> input: 1 output: 1 output: #f input: (+ 3 4) input: + output: #<subr +> input: 3 output: 3 input: 4 output: 4 output: 7 output: 7 == input: (list (and (listp 3) t) (+ 1 2)) input: list output: #<subr list> input: (and (listp 3) t) input: (listp 3) input: listp output: #<subr list?> input: 3 output: 3 output: #f output: #f input: (+ 1 2) input: + output: #<subr +> input: 1 output: 1 input: 2 output: 2 output: 3 output: (#f 3)
何とか計算出来ました><