「...」だと、こうは書けないですよね。。に反応頂きました!
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) | |
;; > |
写経したも同然ですが、早速自分なりに書いてみました。
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-vars | |
(syntax-rules () | |
((_ () body ...) | |
(let () | |
body ...)) | |
((_ ((var val) more ...) body ...) | |
(let ((var val)) | |
(bind-vars (more ...) | |
body ...))) | |
((_ ((var) more ...) body ...) | |
(bind-vars ((var #f)) | |
(bind-vars (more ...) | |
body ...))) | |
((_ (var more ...) body ...) | |
(bind-vars ((var)) | |
(bind-vars (more ...) | |
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) |
オリジナルのコードだとsyntax-errorっての使ってますが、これはR5RSで定義されていないので、errorに差し替えています。今読んでいるところまでには、出てきてないですね。
もっとも、2番目のパターンだとそれじゃあ怒られたので、syntax-errorの挙動がしりたいトコなんですけどねえ。
Gauche では、組み込みであるようです。
実行時ではなくマクロ展開時(すなわち、コンパイル時)に エラーを通知する
追記
あれ、これって「自分で書け」ってお題が出てるんですかね。*** Write a syntax-error macro. Write `rejection' patterns by expanding into a call to syntax-error.
0 件のコメント:
コメントを投稿