Ex. 4.32
遅延度が高いというのは、cons の第1引数が遅延することを指す。3章のストリームでは、これは遅延されない。3章ストリームで遅延されるのはcons の第2引数のみである。
例1. 未知数のストリームが作れる。
(x x x x x ...)
こういうの。3章ストリームだと
(define xs (cons-stream x xs))
x の未定義エラーになる。cons-stream は第1引数の x を評価するからだ。 遅延ストリームだと
(define xs (cons x xs))
エラーにならない。遅延ストリームの cons はどちらの引数も遅延するからだ。
例2. ネストが無限のリストが作れる。
((((...(1)...1) 1) 1) 1)
こういうの。3章ストリームだと
(define ones2 (cons-stream ones2 '(1)))
ones2 の未定義エラーになる。cons-stream は第1引数の ones2 を評価するからだ。 遅延ストリームだと
(define ones2 (cons ones2 '(1)))
エラーにならない。遅延ストリームの cons はどちらの引数も遅延するからだ。
Ex. 4.33
方針: ペアのクォートは cons 式で置き換えてから評価して返す。
'(a b) → (eval (cons 'a (cons 'b '())) the-global-environment)
という感じ。
アトムのクォートはそのまま返す。
'a → a '1 → 1 '() → ()
という感じ。実装は
;; convert a quoted pair into cons expression and then eval it, ;; on the other hand a quoted atom return itself. (define (text-of-quotation exp env) (let ((e (cadr exp))) (if (pair? e) (eval (quote->cons e) env) ;;; quoted pair is converted to cons and evaled e))) ;;; quoted atom returns itsef ;; convert a pair into cons expression ;; like this ;; (a b) -> (cons 'a (cons 'b '())) ;; convert an atom as quoted ;; a -> 'a ;; 1 -> '1 ;; () -> '() (define (quote->cons exp) (if (pair? exp) (list 'cons (quote->cons (car exp)) (quote->cons (cdr exp))) (list 'quote exp))) (define (eval exp env) ... ((variable? exp)(lookup-variable-value exp env)) ((quoted? exp) (text-of-quotation exp env)) ;; changed ((assignment? exp)(eval-assignment exp env)) ...
アトムのクォートの処理がどんくさくて微妙。
Ex. 4.34
まず (cons 1 2) の評価結果は、
(compound-procedure (m) ((m x y)) <procedure-env>) ← ①
となる。procedure として返ってくる。cons を lambda に変換しているのだから当然である。 で、これを印字するときだけ (1 2) としたいわけであるが、、、
まずこの procedure を他の procedure と区別する方法がない。ので何か区別をつける工夫をしてやらねばならない。
面倒なので、あまり正しくない方法であるが、仮引数 m を $cons とかにして仮引数の名前で区別することにする。
次に表示のためにリストの car と cdr を取得せねばならないが、これは ①に car, cdr を apply して取り出すこととする。
あと、無限リストの対応は、面倒なので、リストを10個表示したら、そこで中止するくらい。
以上の方針で、実装しようとしましたが失敗しました。
修正途中のソースは以下のとおり。
;; This doesn't work at all. (define (user-print object) (if (compound-procedure? object) (if (cons-procedure? object) ;;; changed (display (actual-value (apply (actual-value 'car the-global-environment) object the-global-environment)) the-global-environment) ;;; changed (display (list 'compound-procedure (procedure-parameters object) (procedure-body object) '<procedure-env>))) (display object))) (define (cons-procedure? obj) (eq? (caadr obj) '$cons))
あと、子Scheme のcons の定義も変える
;;; L-Eval value: (define (cons x y) (lambda ($cons) ($cons x y))) the-global-environment)
仮引数を m から $cons に変えた。
以上、とりあえずリストの car だけ表示させるつもりで作ったのですが、全然動きません、、、orz、疲れたので 退却~。(^^ゞ