EoPL reading (66) 2.2 An Abstraction for Inductive Data Type
うーん、迷走気味。現時点にて parse な試験で問題発生中。
test unparse (4), expects (lambda (x) (f x y)) ==> ERROR: GOT #<error "wrong number of arguments for #<closure (unparse-expression unparse-expression)> (required 2, got 3)"> test unparse (5), expects (lambda (x) (x)) ==> ERROR: GOT #<error "wrong number of arguments for #<closure (unparse-expression unparse-expression)> (required 2, got 1)">
実装を控え。まず、expression.scm から
(add-load-path ".") (load "define-datatype") (define list-of (lambda (pred) (lambda (val) (or (null? val) (and (pair? val) (pred (car val)) ((list-of pred) (cdr val))))))) (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 (ids (list-of symbol?)) (body expression?)) (app-exp (rator expression?) (rands (list-of expression?))))
次は parse.scm
(add-load-path ".") (load "define-datatype") (define unparse-expression (lambda (exp) (cases expression exp (lit-exp (datum) datum) (var-exp (id) id) (if-exp (test-exp true-exp false-exp) (list 'if test-exp true-exp false-exp)) (lambda-exp (ids body) (list 'lambda ids (unparse-expression body))) (app-exp (rator rands) (list (unparse-expression rator) (unparse-expression rands)) )))) (define parse-expression (lambda (datum) (cond ((number? datum) (lit-exp datum)) ((symbol? datum) (var-exp datum)) ((pair? datum) (cond ((eqv? (car datum) 'lambda) (lambda-exp (cadr datum) (parse-expression (caddr datum)))) ((eqv? (car datum) 'if) (if-exp (cadr datum) (caddr datum) (cadddr datum))) (else (let f ((rslt '(app-exp)) (datum datum)) (if (null? datum) rslt (f (append rslt (list (parse-expression (car datum)))) (cdr datum))))))) (else (eopl:error 'parse-expression "Invalid concrete symtax ~s" datum)))))
あと、parse の試験も以下に。
(use gauche.test) (add-load-path ".") (load "define-datatype") (load "expression") (load "occurs-free") (load "parse") (test-start "parse") (test-section "unparse-expression") (test* "unparse (1)" 'a (unparse-expression '(var-exp a))) (test* "unparse (2)" '(lambda (x) x) (unparse-expression '(lambda-exp (x) (var-exp x)))) (test* "unparse (3)" '((lambda (x) x) a) (unparse-expression '(app-exp (lambda-exp (x) (var-exp x)) (var-exp a)))) (test* "unparse (4)" '(lambda (x) (f x y)) (unparse-expression '(lambda-exp (x) (app-exp (var-exp f) (var-exp x) (var-exp y))))) (test* "unparse (5)" '(lambda (x) (x)) (unparse-expression '(lambda-exp (x) (app-exp (var-exp x))))) (test* "unparse (6)" '(lambda (x y z) x) (unparse-expression '(lambda-exp (x y z) (var-exp x)))) (test* "unparse (7)" '(lambda () x) (unparse-expression '(lambda-exp () (var-exp x)))) (test-section "parse-expression") (test* "parse (1)" '(var-exp a) (parse-expression 'a)) (test* "parse (2)" '(lambda-exp (x) (var-exp x)) (parse-expression '(lambda (x) x))) (test* "parse (3)" '(app-exp (lambda-exp (x) (var-exp x)) (var-exp a)) (parse-expression '((lambda (x) x) a))) (test* "parse (4)" '(lit-exp 5) (parse-expression 5)) (test* "parse (5)" *test-error* (parse-expression "a")) (test* "parse (6)" '(app-exp (var-exp a) (var-exp b) (var-exp c)) (parse-expression '(a b c))) (test* "parse (7)" '(app-exp (lambda-exp (x) (app-exp (var-exp +) (var-exp x) (var-exp x))) (var-exp a)) (parse-expression '((lambda (x) (+ x x)) a))) (test* "parse (8)" '(lambda-exp (x) (app-exp (var-exp x))) (parse-expression '(lambda (x) (x)))) (test-end)
なんとなく見えてるのは
- (app-exp (var-exp f) (var-exp x) (var-exp y)) は引数 3 つなので引数二つな app-exp の呼び出しに対応不可能
- (app-exp (var-exp x)) は引数 1 つなので (ry
という事。だったら app-exp な分岐を以下にしたらどうか、とトライしてみると
discrepancies found. Errors are: test unparse (1): expects a => got #<error "proper list required, but got (rator . rands)"> test unparse (2): expects (lambda (x) x) => got #<error "proper list required, but got (rator . rands)"> test unparse (3): expects ((lambda (x) x) a) => got #<error "proper list required, but got (rator . rands)"> test unparse (4): expects (lambda (x) (f x y)) => got #<error "proper list required, but got (rator . rands)"> test unparse (5): expects (lambda (x) (x)) => got #<error "proper list required, but got (rator . rands)"> test unparse (6): expects (lambda (x y z) x) => got #<error "proper list required, but got (rator . rands)"> test unparse (7): expects (lambda () x) => got #<error "proper list required, but got (rator . rands)">
って叱られる。可変長引数にマッチ可能な syntax-rules の書き方がどうか、が分かれば問題解決なのでしょうか。色々試験してみているんですが、途中中断
ってか今日はこのまま終了。
追記
昨晩、エントリ投入途上で寝落ちしてました。ちなみに盛り込んだ実装は以下になります。
(app-exp (rator rands) ;; (list (unparse-expression rator) ;; (unparse-expression rands)) (append (list (unparse-expression rator)) (if (pair? rands) (unparse-expression rands) (if (null? rands) '() (list rands)))))
解決の糸口が全く見えてません。いったん最初から見直した方が良さげ。