識別子マクロとパラメタによる大域変数エミュレートにそれを解消するマクロが紹介されていた。確かに、ぱっと見よさげだなぁと思ったのだが、これってSRFI-39が提供するparameterizeマクロと相性最悪じゃね?と思ってちょっと実験してみた。
(import (rnrs) (srfi :39)) (define-syntax define-identifier-parameter (syntax-rules () ((_ var val) (begin (define t (make-parameter val)) (define-syntax var (make-variable-transformer (lambda(x) (syntax-case x (set!) ((set! _ a) #'(t a)) (_ #'(t)))))))))) (define-identifier-parameter *variable* 1) (display *variable*) (newline) (parameterize ((*variable* 2)) (display *variable*) (newline)) (display *variable*) (newline)検証はいつもどおり、Sagittarius、YpsilonにMosh。
っで結果:
- Sagittarius
- Ypsilon
- 1を3回出力。(parameterizeされてない)
- Mosh
- &assertion: (1)は関数じゃないと怒られた
面白いけど、使いどころが限定されそうだ。
2 comments:
import して set! できる変数ということだけしか意識しておらず、パラメタであることに特に意味はないつもりだった (cons でも vector でも値を入れられるものなら実装上は何でもよかった) のですが、名前に parameter と付けちゃったのでやっぱり parameter としての振舞いを期待しちゃいますね。
色々と考えてみたのですが、パラメタ関連の手続き (やマクロ) と組み合わせて使う場合は、あくまでも identifier-parameter というものであって parameter とは違うものという意識で間に変換を入れるようにするしかないんじゃないかと思います。
とりあえずこんなものを書いてみました。
http://ideone.com/epC8s
これを利用すれば以下のような要領で parameterize と組み合わせられます。
(parameterize (((identifier-parameter->parameter *variable*) 2))
(display *variable*)
(newline))
このままだと冗長ですが、好みにあわせて短い記法を用意すればそれなりに使えるんじゃないでしょうか。
identifier-parameterであってparameterではないというのはありかもしれませんね。
set!で変更可能となると、「取り扱い注意」のラベルが必要かもしれませんが。
Post a Comment