Gauche:FeatureIdentifier

Gauche:FeatureIdentifier

Shiro: 2007/03/29 02:19:39 PDT

システムによって有ったり無かったりする機能を、ユーザプログラムにどうやってハンドルさせるか、という話。要はCで書くときの

#if defined(HAVE_FOO)
... fooを使ったコード ...
#else
... 代替コード
#endif

みたいなことをSchemeで出来るようにしたい。0.8.10に入れたいところだが、間に合わなければ もう少し後になるかも。

基本はcond-expand

基本方針として、こういう切り替えは全てcond-expandでやりたい。(GaucheRefj:cond-expand)

(if (global-variable-bound? ...) ...) 等の方法は、

という欠点があるため。

cond-expandを使うとなると、特定の機能があることを示すfeature-identifierを どう管理するか、ということを考えなければならない。特に、ユーザ提供の拡張モジュールに ついて、柔軟かつロバストにfeature-identifierをシステムに追加してゆく方法が 必要である。

要求仕様。

方針。

コンパイル時だけ別のfeature setを使う

Windows/VC++版で、*.scm -> *.c のprecompilationをクロスでやる必要が 出てきたのでなんとかしないとならなくなった。 とりあえず拡張パッケージのことは考えず、メインのGaucheのfeature setは コンパイルインされているものとする。

最初のふたつは難しくない。後のふたつはどうするのが良いだろうか。

  1. feature setをコンパイル時環境に加える (現在のところ、 コンパイル時環境は module(グローバル環境) + レキシカル環境)
  2. parameterで持ち回る。
  3. feature identifierをsyntacticな束縛としてグローバル環境に加える。 (「syntacticな束縛」はdefineやlambdaなどコンパイラが認識する束縛ってこと)。

1, 2は通常の束縛とは直交する名前空間を持つことになるので あんまり綺麗じゃない (現状もそうだけど)。 3は名前空間のルールが統一されてすっきりするけど、うっかりユーザモジュール内で feature identifierと同名のグローバル変数を定義してしまうと 元のfeature identiferがシャドウされてしまうとかいう落とし穴があるかも。 (R6RS的に、束縛の衝突を許さないことにすれば安全なんだけど、 影響がでかいしなあ)。 一番簡単なのは2.かなあ。


Last modified : 2007/10/07 06:35:56 UTC