EoPL reading (101) 2.2 An Abstraction for Inductive Data Type
日を跨いだのでエントリを分けます。煮つまったので氷を買うついでに散歩。散歩しつつ、app-term なナニは分けちゃえ、な思いつきを基に以下がでっち上がりました。
(define app-parse (lambda (datum) (if (null? datum) '() (cons (parse (car datum)) (app-parse (cdr datum)))))) (define parse (lambda (datum) (cond ((symbol? datum) (var-term datum)) ((constant? datum) (constant-term datum)) ((pair? datum) (app-term (app-parse datum))) (else (eopl:error 'parse "Invalid syntex ~s" datum)))))
list に惑わされたりなんかしましたが、以下の試験にパスしてます。
(use gauche.test) (add-load-path ".") (load "parse") (test-start "parse") (test-section "parse") (test* "(parse 'x)" '(var-term x) (parse 'x)) (test* "(parse #t)" '(constant-term #t) (parse #t)) (test* "(parse #f)" '(constant-term #f) (parse #f)) (test* "(parse 0)" '(constant-term 0) (parse 0)) (test* "(parse \"a\")" '(constant-term "a") (parse "a")) (test* "(parse '(\"cons\" w x))" '(app-term ((constant-term "cons") (var-term w) (var-term x))) (parse '("cons" w x))) (test* "(parse '(\"append\" (\"cons\" w x) y (\"cons\" w z)))" '(app-term ((constant-term "append") (app-term ((constant-term "cons") (var-term w) (var-term x))) (var-term y) (app-term ((constant-term "cons") (var-term w) (var-term z))))) (parse '("append" ("cons" w x) y ("cons" w z)))) (test-end)
いいのかなぁ。とりあえず 0100 過ぎてるんですが unparse に着手するかどうか悩ましい。
unparse
簡単なナニの試験を書いてみた。
(use gauche.test) (add-load-path ".") (load "unparse") (test-start "unparse") (test-section "unparse") (test* "(unparse '(var-term x))" 'x (unparse '(var-term x))) (test* "(unparse '(constant-term #t))" #t (unparse (constant-term #t))) (test* "(unparse '(constant-term #f))" #f (unparse (constant-term #f))) (test* "(unparse '(constant-term '()))" '() (unparse (constant-term ()))) (test* "(unparse '(constant-term 0))" 0 (unparse (constant-term 0))) (test* "(unparse '(constant-term \"a\"))" "a" (unparse (constant-term "a"))) (test-end)
app-term は今のところ略。原型が以下。
(add-load-path ".") (load "term") (define unparse (lambda (l) (cases term l (var-term (id) ) (constant-term (datum) ) (app-term (terms) ) )))
よく考えたら var-item とか constant-item とかってそのまんまじゃん。
(add-load-path ".") (load "term") (define unparse (lambda (l) (cases term l (var-term (id) id) (constant-term (datum) datum) (app-term (terms) ) )))
試験はパス。
Testing unparse =============================================================== <unparse>---------------------------------------------------------------------- test (unparse '(var-term x)), expects x ==> ok test (unparse '(constant-term #t)), expects #t ==> ok test (unparse '(constant-term #f)), expects #f ==> ok test (unparse '(constant-term '())), expects () ==> ok test (unparse '(constant-term 0)), expects 0 ==> ok test (unparse '(constant-term "a")), expects "a" ==> ok
このあたりは楽勝なんですが次がねぇ。
で、でっち上げたのが以下な試験と
(test* "(unparse '(app-term ((constant-term \"cons\") (var-term a) (var-term b))))" '("cons" a b) (unparse (app-term (list (constant-term "cons") (var-term 'a) (var-term 'b)))))
以下な手続き。
(add-load-path ".") (load "term") (define unparse (lambda (l) (cases term l (var-term (id) id) (constant-term (datum) datum) (app-term (terms) (let f ((rslt '()) (list terms)) (cond ((null? list) rslt) (else (f (append rslt (list (unparse (car list)))) (cdr list)))))))))
何故に f の引数を list にしたのだと小一時間 (あるいは二時間)。変数の名前がダメ、って事に気づいて今に至ってます。
修正後のソレが以下。
(add-load-path ".") (load "term") (define unparse (lambda (exp) (cases term exp (var-term (id) id) (constant-term (datum) datum) (app-term (terms) (let f ((rslt '()) (l terms)) (cond ((null? l) rslt) (else (f (append rslt (list (unparse (car l)))) (cdr l)))))))))
上記の試験にはパスしてます。気が狂うかと思った。変数名の付けかたには気をつけねば、と思いつつも同じコトを繰り返しております。
もう少し複雑なナニの試験は明日。