2008-01-04
■ [biwascheme] let*の変換
let*はletのネストに変換できる。*1
(let* ((a 1) (b a)) (print a) (+ a b))
↓
(let ((a 1))
(let ((b a))
(print a) (+ a b)))
ということで、
- バインディングを最後から順番に取って、
- body = (let (bind) (body)) とする
という操作を繰り返せばよい。
…のだが、biwaschemeではbodyに複数の式を許しているので、最初だけ特別扱い(Pairで包まない)しなければならない。
var ret = null;
binds.to_array().reverse().each(function(bind){
ret = new Pair(Sym("let"),
new Pair(new Pair(bind, nil),
ret == null ? body : new Pair(ret, nil)));
})
return ret;
というのでちょっと悩んだ。
再帰的に書けばこんな罠にははまらないっぽいんだが。
syntax-rulesで書いてみた例。
(define-syntax letstar
(syntax-rules ()
((letstar ((var val)) body ...)
(let ((var val)) body ...))
((letstar ((var val) (var2 val2) ...) body ...)
(let ((var val))
(let* ((var2 val2) ...) body ...)))))
(print (let ((x 2) (y 3)) (let* ((x 7) (z (+ x y))) (list x y z))))
*1 letは最終的にlambdaに変換できるので、let*から直接lambdaに変換しても良いと思う
■ [scheme] syntax-rulesでdefine-structをつくる
去年書き忘れた記事。
MzSchemeにはdefine-structという構文(Common Lispのdefstructみたいなもの)があるらしくて、 Gaucheにもあったらいいなぁと思ったので作ってみた。
…とさらっと書いたけど非常に苦労しましたw
;; string-appendのシンボル版
(define (symbol-append . syms)
(string->symbol
(apply string-append (map symbol->string syms))))
;; define-structという構文を定義
(define-syntax define-struct
(syntax-rules ()
((define-struct name props)
(eval
`(begin
(define-class
,(symbol-append '< 'name '>)
()
,(map
(lambda (sym)
`(,sym :init-keyword ,(make-keyword sym)
:accessor ,(symbol-append sym '-of- 'name)))
'props))
,@(map
(lambda (sym)
`(define-method ,(symbol-append 'name '- sym '-set!)
((obj ,(symbol-append '< 'name '>)) ,sym)
(slot-set! obj ',sym ,sym)))
'props))
(interaction-environment)))))
使用例。
(define-struct book (title jp-title)) (let1 bk (make <book> :title "SICP") (print (title-of-book bk)) (book-jp-title-set! bk "(前略)構造と解釈") (print (jp-title-of-book bk)) )
はっきり言ってsyntax-rules使う意味がない(パターンマッチ使ってない)。 define-macroで書き直してみようかと思ったけど気力が尽きたので省略。 あとevalをなんとかしたかったけど無理だった。
先輩はevalなし(syntax-rulesだけ)でできるって言うんだけどさ、無理じゃね? syntax-rulesじゃマクロ展開時にsymbol-appendを実行することができないんだし。
syntax-rulesでsymbol-appendが実装できれば別だけど…、いくらチューリング完全と言っても、 それはリスト操作についてであって、symbol->stringが実装できるわけではない。よね。
[ツッコミを入れる]