(bind-variables ((a 1) (b) c e (d (+ a 3))) (list a b c d e)) ;; -> (1 #f #f 4 #f)
で、自分なりに書いてはみたものの・・・。かなり苦戦しました。
しかも複雑になってしまって、何が何やら。動いてはいるっぽいものの、これじゃーちょっと・・・。それに何よりダサい。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; vind-vars | |
;; vind-variables http://web.archive.org/web/20060616054033/home.comcast.net/~prunesquallor/macro.txt | |
(define-syntax bind-vars | |
(syntax-rules () | |
((_ () body ...) | |
(let () | |
body ...)) | |
((_ ((var init)) body ...) | |
(let ((var init)) | |
body ...)) | |
((_ ((var1 init1)(var2 init2) ...) body ...) | |
(bind-vars ((var1 init1)) | |
(bind-vars ((var2 init2) ...) | |
body ...))) | |
((_ ((var1)) body ...) | |
(bind-vars ((var1 #f)) body ...)) | |
((_ ((var1)(var2) ...) body ...) | |
(bind-vars ((var1)) | |
(bind-vars ((var2) ...) | |
body ...))) | |
((_ ((var1)(var2 init2) ...) body ...) | |
(bind-vars ((var1)) | |
(bind-vars ((var2 init2) ...) | |
body ...))) | |
((_ (var) body ...) | |
(bind-vars ((var)) | |
body ...)) | |
((_ (var1 var2 ...) body ...) | |
(bind-vars (var1) | |
(bind-vars (var2 ...) body ...))) | |
((_ (var1 (var2) ...) body ...) | |
(bind-vars (var1) | |
(bind-vars ((var2) ...) body ...))) | |
((_ (var1 (var2 init2) ...) body ...) | |
(bind-vars (var1) | |
(bind-vars ((var2 init2) ...) body...))))) | |
(bind-vars ((a 1) | |
(b) | |
c | |
e | |
(d (+ a 3))) | |
(list a b c d e)) | |
;; (1 #f #f 4 #f) | |
(let ((a 1)) | |
(bind-vars ((b) | |
c | |
e | |
(d (+ a 3))) | |
(list a b c d e))) | |
;; (1 #f #f 4 #f) | |
(let ((a 1)) | |
(let ((b #t)) | |
(bind-vars (c | |
e | |
(d (+ a 3))) | |
(list a b c d e)))) | |
;; (1 #t #f 4 #f) | |
(bind-vars (a b c d e) | |
(list a b c d e)) | |
;; (#f #f #f #f #f) | |
(bind-vars ((a)(b)(c)(d)(e)) | |
(list a b c d e)) | |
;; (#f #f #f #f #f) | |
(bind-vars (a (b 1)(c 2) d (e)) | |
(list a b c d e)) | |
;; (#f 1 2 #f #f) | |
お手本はこちら。うーん、だいぶスッキリしていますね。「...」だと、こうは書けないですよね。。場合によってはドット対表現で書いた方がスッキリするんですね。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; vind-variables http://web.archive.org/web/20060616054033/home.comcast.net/~prunesquallor/macro.txt | |
(define-syntax bind-variables | |
(syntax-rules () | |
((bind-variables () form . forms) | |
(begin form . forms)) | |
((bind-variables ((variable value0 value1 . more) . more-bindings) form . forms) | |
(syntax-error "bind-variables illegal binding" (variable value0 value1 . more))) | |
((bind-variables ((variable value) . more-bindings) form . forms) | |
(let ((variable value)) (bind-variables more-bindings form . forms))) | |
((bind-variables ((variable) . more-bindings) form . forms) | |
(let ((variable #f)) (bind-variables more-bindings form . forms))) | |
((bind-variables (variable . more-bindings) form . forms) | |
(let ((variable #f)) (bind-variables more-bindings form . forms))) | |
((bind-variables bindings form . forms) | |
(syntax-error "Bindings must be a list." bindings)))) | |
(bind-variables ((a 1) | |
(b) | |
c | |
e | |
(d (+ a 3))) | |
(list a b c d e)) | |
;; (1 #f #f 4 #f) | |
(let ((a 1)) | |
(bind-variables ((b) | |
c | |
e | |
(d (+ a 3))) | |
(list a b c d e))) | |
;; (1 #f #f 4 #f) | |
(let ((a 1)) | |
(let ((b #t)) | |
(bind-variables (c | |
e | |
(d (+ a 3))) | |
(list a b c d e)))) | |
;; (1 #t #f 4 #f) | |
(bind-variables (a b c d e) | |
(list a b c d e)) | |
;; (#f #f #f #f #f) | |
(bind-variables ((a)(b)(c)(d)(e)) | |
(list a b c d e)) | |
;; (#f #f #f #f #f) | |
(bind-variables (a (b 1)(c 2) d (e)) | |
(list a b c d e)) | |
;; (#f 1 2 #f #f) | |
追記
書けてるー(笑)なるほどー。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(define-syntax bind-variables | |
(syntax-rules () | |
((_ () form ...) | |
(begin form ...)) | |
;; ここはオリジナルの syntax-error がどんな挙動か分からないので割愛 | |
;; error で置き換えてみたが、本体に form ... が無い、と怒られた | |
;; ((_ ((var val0 val1 ...) ...) form ...) | |
;; (error "bind-variables illegal binding" (var val0 val1 ...))) | |
((_ ((var val) more-bindings ...) form ...) | |
(let ((var val)) (bind-variables (more-bindings ...) form ...))) | |
((_ ((var) more-bindings ...) form ...) | |
(let ((var #f)) (bind-variables (more-bindings ...) form ...))) | |
((_ (var more-bindings ...) form ...) | |
;; ここは、本当は上のパターンに差し替えたほうが綺麗かも | |
(let ((var #f)) (bind-variables (more-bindings ...) form ...))) | |
((_ bindings form ...) | |
(error "Bindings must be a list." bindings)) | |
)) | |
;; ;; 実行例 | |
;; > (bind-variables ((a 1) | |
;; (b) | |
;; c | |
;; e | |
;; (d (+ a 3))) | |
;; (list a b c d e)) | |
;; (1 #f #f 4 #f) | |
;; > (let ((a 1)) | |
;; (bind-variables ((b) | |
;; c | |
;; e | |
;; (d (+ a 3))) | |
;; (list a b c d e))) | |
;; (1 #f #f 4 #f) | |
;; > (let ((a 1)) | |
;; (let ((b #t)) | |
;; (bind-variables (c | |
;; e | |
;; (d (+ a 3))) | |
;; (list a b c d e)))) | |
;; (1 #t #f 4 #f) | |
;; > (bind-variables (a b c d e) | |
;; (list a b c d e)) | |
;; (#f #f #f #f #f) | |
;; > (bind-variables ((a) (b) (c) (d) (e)) | |
;; (list a b c d e)) | |
;; (#f #f #f #f #f) | |
;; > (bind-variables (a (b 1) (c 2) d (e)) | |
;; (list a b c d e)) | |
;; (#f 1 2 #f #f) | |
;; > |
R5RS においては、 syntax-rules のパターン部にドット対を用いた表現が許されますが、テンプレート部をドット対で組み立てるのは未定義だとされています。
返信削除なので、なるべく ... (ellipsis) を使った表現が好ましいと思います。
とは言うものの、 R6RS では問題なく使えますし、 R5RS を名乗る処理系の中でテンプレート部にドット対表現が使えないものを見付けられないので実質的には問題にならないでしょうけど。
いつも教えて頂いてありがとうございます!
返信削除勉強になります。
>R5RS においては、 syntax-rules のパターン部にドット対を用いた表現が許されますが、テンプレート部をドット対で組み立てるのは未定義だとされています。
えー!そうなんですか・・・。また微妙な・・・。
やっぱり、R5RSを読まないとダメですね。。「いつか実装する時でいいや。」と思っていましたが、そうもいかないですね^^;
「テンプレート部に」というよりは「Scheme の式に」と言った方が正確でした。
返信削除例えば (display . ('a)) とすれば普通に a を表示します。 しかし、 R5RS にある手続き呼出しの構文は ( ...) という形式だけです。 ( . ( ...)) と言う形式で手続きが呼出せる根拠がないのです。
R6RS でこれが問題なくなるのは、 Scheme のプログラムがS式である旨が明記されたからです。 S式としては書き方がどっちであっても同じと見做せるので問題ありません。
逆に言えば R5RS では Scheme のプログラムはS式でないことになります。 (少くとも明記されてはいません。) これは結構衝撃的な話です。
CommonLisp 派が「Scheme は Lisp ではない」と主張する根拠のひとつとして挙げていたのでそれなりに有名な話ではあるのですが、 R5RS だけをよほどきちんと読んでも気付ける人はかなり少ないんじゃないかと思います。
あれ、コメント中に山括弧使ったら消えちゃった。
返信削除ふたつ目の段落だけ再度書きます。
例えば (display . ('a)) とすれば普通に a を表示します。 しかし、 R5RS にある手続き呼出しの構文は ( 演算子 オペランド ...) という形式だけです。 ( 演算子 . (オペランド ...)) と言う形式で手続きが呼出せる根拠がないのです。
>逆に言えば R5RS では Scheme のプログラムはS式でないことになります。 (少くとも明記されてはいません。) これは結構衝撃的な話です。
返信削除めちゃくちゃ衝撃的な話ですねそれ!(笑)