set!で変更可能となると、「取り扱い注意」のラベルが必要かもしれませんが。よく考えてみると、Sagittariusでは以下のようなことができる。
(library (test)
(export variable)
(import (rnrs))
(define variable 1))
(import (test))
(set! variable 2)
(print variable)
#|
;; Output
2
|#
これはR6RS的にはエラーにならないとまずい。記憶が正しかったら、R7RS的にもエラーだったはず。Sagittariusではデフォルト(というか、現状だと必ず)「取り扱い注意」のラベルが要ることになる。直すかなぁ。変更できた方が便利だろうかと思ったんだけど、変更されない方が便利だよなぁ。
でも、Ypsilonでも#!r6rsをつけないとエラーにならないなぁ。 どうしよう?
とりあえず、実行時エラーにするようにしてみた。ただ、これコンパイルエラーにした方がいろいろ嬉しいのだが、それをやると非常に不便になる。以下が不便になる例。
(library (test)
(export variable)
(import (rnrs))
(define variable 1)
)
(library (test2)
(export variable)
(import (rnrs) (test))
(define variable 'hoge) ; ここ
(define (aa) (set! variable 2))
)
R6RSやR7RS的にはコメントで示している部分はエラーにならないといけないんだけど、それやるとSRFIとかでガチンコでぶつかっている手続きがエラーになる。(removeとか、振る舞いまで違うから再定義せざるを得ない)。実はコンパイル時に再定義を不可にすることは出来るんだけど、やるといろんな場所に修正が走るのでやりたくない。テストカバレッジが100%ならまだ楽なんだろうけど、残念ながらそうでもないのが更にやりたくなさを加速させている。
Scheme的にどちらが正しいかは置いておいて、ユーザ的にはどっちの方が嬉しいのか気になるところ。
僕は再定義可能に1票。(これも揺れるところだけど・・・)
2 comments:
R6RSのimportはidentifierをそのまま持ち込むので、再定義はそのidentifierの意味を変えてしまうためにエラーとされてるのでしょう。
Gaucheのimportセマンティクスは「束縛の可視性」を持ち込むので、再定義すると単にそれまで見えていた(importしていた)束縛がシャドウされるだけです。同名のidentifierをexportしているライブラリを順にimportしても、コンフリクトせずに後からimportした方がシャドウします。これはルーズに開発している時は便利なのですが、可視性がimportの順序に依存するとか、色々不都合もあります。
R6RSのimportはそれはそれで便利だと思うんですけど、僕はGaucheチックな解決の仕方を選択したみたいで、ばっちりimport順に依存しています。
それのせいで(おかげで?)あんまり再定義に抵抗がなかったのですが、それでいいのかなぁ?と疑問に思えてきたのもあるので、いろんな意見が聞きたいなぁと思った次第です。
Post a Comment