取りあえず書いてみたのがこれ。微妙っぽい。
で、PDF に書いてあったのは、こういうの。
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
;; reverse-and-quote-list | |
(define-syntax reverse-and-quote-list | |
(syntax-rules () | |
((_ lis) | |
(let loop ((l (quote lis)) | |
(acc '())) | |
(if (null? l) | |
acc | |
(loop (cdr l)(cons (car l) acc))))))) | |
(reverse-and-quote-list (1 2 3 4 5)) | |
; -> (5 4 3 2 1) |
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
;; http://people.csail.mit.edu/jhbrown/scheme/macroslides03.pdf | |
(define-syntax reverse-and-quote-list | |
(syntax-rules () | |
((_ lis) | |
(rl-helper lis ())))) | |
(define-syntax rl-helper | |
(syntax-rules () | |
((_ () (backw ...)) | |
'(backw ...)) | |
((_ (arg rest ...)(backw ...)) | |
(rl-helper (rest ...)(arg backw ...))))) | |
(reverse-and-quote-list (1 2 3 4 5)) | |
; -> (5 4 3 2 1) |
なるほどー!
これは、letrec-syntaxとやらで、rl-helperをローカルに定義できるのでは?
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 reverse-and-quote-list | |
(letrec-syntax | |
((helper | |
(syntax-rules () | |
((_ () (backw ...)) | |
'(backw ...)) | |
((_ (arg rest ...)(backw ...)) | |
(helper (rest ...)(arg backw ...)))))) | |
(syntax-rules () | |
((_ lis) | |
(helper lis ()))))) | |
;; *** ERROR: Compile Error: syntax-error: malformed define-syntax: (define-syntax reverse-and-quote-list (letrec-syntax ((helper (syntax-rules () ((_ () (backw |...|)) '(backw |...|)) ((_ (arg rest |...|) (backw |...|)) (helper (rest |...|) (arg backw |...|)))))) (syntax-rules () ((_ lis) (helper lis ()))))) | |
;; "(stdin)":23:(define-syntax reverse-and-quote-lis ... | |
(define-syntax reverse-and-quote-list | |
(syntax-rules () | |
((_ lis) | |
(letrec-syntax | |
((helper | |
(syntax-rules () | |
((_ () (backw ...)) | |
'(backw ...)) | |
((_ (arg rest ...)(backw ...)) | |
(helper (rest ...)(arg backw ...)))))) | |
(helper lis ()))))) | |
;; *** ERROR: Compile Error: in definition of macro reverse-and-quote-list: a template contains repetition of constant form: (backw |...|) | |
;; "(stdin)":34:(define-syntax reverse-and-quote-lis ... |
エラー。うーん。間違ってるのはどこだろう。。エラーメッセージもよくわからない。
letrec-syntax, let-syntax は余計に情報少ないな・・・(web)。
追記
これは動きますね。。
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
(letrec-syntax | |
((helper | |
(syntax-rules () | |
((_ () (backw ...)) | |
(quote (backw ...))) | |
((_ (arg rest ...)(backw ...)) | |
(helper (rest ...)(arg backw ...)))))) | |
(helper (1 2 3 4 5) ())) | |
; -> (5 4 3 2 1) |
どういうことかよくわかりません。
define-syntaxの直下にletrec-syntaxが来る形はGaucheではまだサポートされていません。(Gauche 0.9ではr5rsに出てくる形 (define-syntax name (syntax-rules ...)) だけ受けつけます)。
返信削除2番めのやつは、syntax-rulesがネストしているためです。外側にあるsyntax-rulesがテンプレート中にある '...' も全て展開しようとしてしまいますが、外側のsyntax-rulesにとってはbackwというのはパターン変数ではなく初出の識別子なので、いくつ繰り返せば良いのかわかりません。やりたいことは、外側のsyntax-rulesが展開した結果に (backw ...) を含めたい、ということです。このように「展開した結果に...を含める」には (... ...) と書くことにR6RSではなっています。Gaucheでは未サポートです。
define-syntax 直下の letrec-syntax は現在未サポートなんですね。よく知らないまま letrec よろしく使おうとしていました^^;
返信削除「まだ」ということは、将来的にサポートされる予定なんでしょうか。
ネストした syntax-rules では、R6RS 対応の処理系だと(... ...)で動くということですね。こちらも試してみます。
reverse-and-quote-list は補助マクロもローカルマクロも使わない形で、書きなおしてみました。
http://valvallow.blogspot.com/2010/05/re-reverse-and-quote.html
dotted list を使う方法もあります。
返信削除(define-syntax reverse-and-quote-list
(syntax-rules ()
((_ lis)
(letrec-syntax
((helper
(syntax-rules ()
((_ () backw)
'backw)
((_ (arg . rest) backw)
(helper rest (arg . backw))))))
(helper lis ())))))
R6RS に対しては規格内のはずです。
R5RS では規格外ですが、 R5RS 処理系を名乗るいくつかの処理系では動きます。
残念ながら Gauche では駄目でした。
おー!これなら(... ...)でなくても書けるわけですね。
返信削除上記のコードをコピーして、私もGaucheで試してみました。少しいじったりしてみましたが、やはり動きませんでした。
dotted listを使ったり、...だったり、いろいろ書き方があるんですね。
そういえば、下記のようなコードを書いたりしたことがありました。(Gaucheで)
;; http://valvallow.blogspot.com/2010/02/tss-letcc-try.html
(define-syntax try
(syntax-rules ()
((try var a . b)
(letcc success
(letcc var (success a)) . b))))