まぁ、理解できたが、じゃあ既存の実装はどうなってるの?と思い調べてみた。
調査対象:Petite Chez Scheme、Ypsilon、mosh(nmosh)
調査プログラム
(library
(my-lib1 (1))
(export bigger?)
(import (rnrs))
(define (bigger? x)
(or (> x 10))))
(library (my-lib2)
(export sub)
(import (for (my-lib1) (meta 1)) ; run expand (meta 0) (meta 1) (meta 2)に適宜変更
(rnrs))
(define-syntax sub
(lambda (x)
(syntax-case x ()
((_ a b)
(or (bigger? (syntax->datum #'a))
(syntax
(let ((x b))
(- 10 b)))))))))
(library (my-lib3)
(export result)
(import (my-lib2)
(rnrs))
(define (result x)
(sub 10 x)))
(import (my-lib3)
(rnrs))
(display (result 10))
こんなの。特に何の意味もないプログラムだが、フェーズを調べるには必要十分なのでOK。で、結果。
run:
petite: 0
Ypsilon: 0
nmosh: error bigger?がない
expand:
petite: 0
Ypsilon: 0
nmosh: 0
(meta 0):
petite: 0
Ypsilon: 0
nmosh: error bigger?がない
(meta 1):
petite: 0
Ypsilon: 0
nmosh: 0
(meta 2):
petite: 0
Ypsilon: 0
nmosh: error bigger?がない
見た感じとして、Petite、Ypsilonはフェーズ関係をガン無視してるくさい。Shibuya.lisp #2か#3だかの資料によると、バグくさいのも実装したと言っているので、意図的?なものかもしれない。Petiteはよく知らん。
逆にnmoshはこの辺の宣言がきちんとされていないとまずいみたい。これはAndre Van Tonderのexpanderがそういう実装なのだろう。
この辺は仕様書に明確に書いてあるので、nmoshが正解なのだろうが、そんなもの考えてプログラム書きたくないなぁと思うとYpsilon実装にした方がいいのか?
2 comments:
それは implicit phasing という仕組みです。
for での指定からでなくプログラム (ライブラリ)の内容からフェイズが決定されます。
r6rs の 7.2 節の最後の段落でレベルとフェイズの不整合を許容してもよいという記述があるので、for 指定を無視するような実装が必ずしも仕様違反とは言えません。
このあたりはまだ議論が十分でなく、まだ決めかねているというのが実際のところのようです。
ちなみに、 larceny や Iron Scheme は指定に従います。
読み飛ばした(あまりうまく理解できなかった)部分でしたが、そういう意味だったんですね^^;
解説ありがとうございます。
Post a Comment