Exercise 2.11 (2)
またまたちょっとだけ。昨日の朝の続き。
問題点としては以下な模様。
- 渡す lambda な S 式は expression な形になっている必要あり
- parse すれば良いのか
- primapp-exp を expression.scm に追加
- fresh_id.scm も修正必要
- lexical-address と expression が混在
- fresh_id.scm は expression を使用
- lambda-calculus-subst.scm は expression を使用
- occurs-free.scm で lexical-address 使用
あら、lexical-address を使っていない occurs-free はどっかにないかな。
無かったので
でっちあげた。以下。
(add-load-path ".") (load "expression") (define occurs-free? (lambda (var exp) (cases lexical-address exp (lit-exp (datum) #t) (var-exp (id) (eqv? var id)) (if-exp (test-exp true-exp false-exp) (or (occurs-free? var test-exp) (occurs-free? var true-exp) (occurs-free? var false-exp))) (lambda-exp (id body) (and (not (eqv? id var)) (occurs-free? var body))) (app-exp (rator rand) (or (occurs-free? var rator) (occurs-free? var rand))))))
本当かなぁ。
で次。expression.scm を以下に。
(add-load-path "../../define-datatype") (load "define-datatype") (define-datatype expression expression? (lit-exp (datum number?)) (var-exp (id symbol?)) (if-exp (test-exp expression?) (true-exp expression?) (false-exp expression?)) (lambda-exp (id symbol?) (body expression?)) (app-exp (rator expression?) (rand expression?)) (primapp-exp (prim symbol?) (rand1 expression?) (rand2 expression?)))
これも試験必要ですね。そして fresh-id.scm も以下に。
(add-load-path ".") (load "expression") (use srfi-1) (define enum-filter-vars (lambda (exp) (delete-duplicates (flatten (enum-vars exp))))) (define (flatten xs) (cond ((null? xs) '()) ((pair? xs) (append-map flatten xs)) (else (list xs)))) (define all-ids (lambda (exp) (delete-duplicates (flatten (enum-ids exp))))) (define enum-ids (lambda (exp) (cases expression exp (var-exp (id) id) (lambda-exp (id body) (cons id (all-ids body))) (app-exp (rator rand) (cons (all-ids rator) (all-ids rand))) (priapp-exp (prim rand1 rand2) (cons (all-ids rand1) (all-ids rand2)))))) (define fresh-id (lambda (exp s) (let ((syms (all-ids exp))) (letrec ((loop (lambda (n) (let ((sym (string->symbol (string-append s (number->string n))))) (if (memv sym syms) (loop (+ n 1)) sym))))) (loop 0)))))
こいつらどこかに試験があるはずなのでサルベージしてみます。
- occurs-free は Ex.2.8 で試験を書いている
- fresh-id は Ex.2.10 で試験を書いている
- expression の試験は無いのでスルー
で、上記試験はパスしてる風なのですが、肝心の lambda-calculus-subst な試験がパスせず。これはまた別途、ってことになるのかどうかorz
しかも occurs-free? な試験が微妙。微妙なのはコピィ元だったりしてorz
微妙なのは
expression な定義だったりするのかも、と思いはじめていたりしてます。現状以下。
(add-load-path "../../define-datatype") (load "define-datatype") (define-datatype expression expression? (lit-exp (datum number?)) (var-exp (id symbol?)) (if-exp (test-exp expression?) (true-exp expression?) (false-exp expression?)) (lambda-exp (id symbol?) (body expression?)) (app-exp (rator expression?) (rand expression?)) (primapp-exp (prim (lambda (x) (or (eqv? '+ x) (eqv? '* x)))) (rand1 expression?) (rand2 expression?)))
lambda-calculus-subst の試験が以下で
(use gauche.test) (add-load-path ".") (load "parse-expression") (load "lambda-calculus-subst") (test-start "lambda-calculus-subst") (test-section "lambda-calculus-subst") (test* "occurs-bound" '(lambda-exp (p0) (primapp-exp + (var-exp p0) (primapp-exp * (var-exp p) (lit-exp 3)))) (lambda-calculus-subst (parse-expression '(lambda (p) (+ p x))) (parse-expression '(* p 3)) 'x)) (test* "occurs-free" '(lambda-exp (q) (primapp-exp + (var-exp q) (primapp-exp * (var-exp p) (lit-exp 3)))) (lambda-calculus-subst (parse-expression '(lambda (q) (+ q x))) (parse-expression '(* p 3)) 'x)) (test-end)
以下なエラーが出てます。備忘まで。
test occurs-bound, expects (lambda-exp (p0) (primapp-exp + (var-exp p0) (primapp-exp * (var-exp p) (lit-exp 3)))) ==> ERROR: GOT #<<error> "primapp-exp \"Expected 3 arguments but got 2 arguments. Fields are: (prim rand1 rand2) Args are: ((var-exp p) (primapp-exp * (var-exp p) (lit-exp 3)))"
ぐぬぬ。