2010/06/02

Re: syntax-rules: bind-variables

「...」だと、こうは書けないですよね。。
に反応頂きました!
(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)
;; >

写経したも同然ですが、早速自分なりに書いてみました。
(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)
view raw bind-vars2.scm hosted with ❤ by GitHub



オリジナルのコードだとsyntax-errorっての使ってますが、これはR5RSで定義されていないので、errorに差し替えています。
もっとも、2番目のパターンだとそれじゃあ怒られたので、syntax-errorの挙動がしりたいトコなんですけどねえ。
今読んでいるところまでには、出てきてないですね。
Gauche では、組み込みであるようです。
実行時ではなくマクロ展開時(すなわち、コンパイル時)に エラーを通知する

追記

あれ、これって「自分で書け」ってお題が出てるんですかね。
*** Write a syntax-error macro.
    Write `rejection' patterns by expanding into a call to
    syntax-error.

プログラミングGauche

0 件のコメント:

コメントを投稿