R6RS互換ライブラリの方針を考える

基本的に、nmoshでのプログラミングはyuniを推奨するようにしたいと考えている。yuniはR6RS実装にR7RSの語彙を提供するので、少くともR7RSの範囲(と、yuniFFIが提供するネイティブOSインターフェース)で書ける範囲のプログラムは問題なく記述できる。
問題は既存の何十とあるR6RSプログラムで、これらをスムースに移行していく手段が必要になる。プログラミングの上でも、fold-leftのようなR6RSリストライブラリを個人的には愛用しているので、できれば同じ語彙を継続して使用したい。

R6RS語彙を分類する

まず、R6RSを分類して扱いを決める:

  • a) yuniライブラリの一部として併合する - fold-leftのようなリストライブラリ、put-bytevectorのようなput系ポート手続き、...
  • b) 移植用にR7RS実装を用意する - 16bits以上のbytevectors、Unicode、fixnum、flonum...
  • c) 同じ名前で全く互換性が無いのでエラーになるようにする - bytevector-copy!
  • d) 実装困難なので見捨てる - custom I/Oポート、condition types、records、transcoders、...
  • e) 望ましくない機能なので実装しない - identifier-syntax、syntax-case、...
  • f) 多分誰も使っていない - enum

a、b、cは実装する。特に、aグループの語彙は(yuni scheme)ライブラリに普通に追加する。bグループは(yuni rnrs compat)、cグループは(yuni rnrs porting)とする。ただし、手続きが発生させる例外等はR7RS相当のものとなる。これはcondition type等のエラー表現を実装しないことによる。
bytevectorsをaに入れないのは、yuniはlittle/big/nativeの各エンディアンしか求めていないのでendianness指定子によるR6RSのインターフェースは冗長なため。Unicodeをどの程度真面目にやるかは要検討。
今のところbytevector-copy!くらいしか互換性の無い機能には気付いていないが、精査する必要が有るかも。R7RSはR6RSとの非互換性について1節割いているが、このような移植性の問題には特に言及していない。
dグループの立場が一番難しい。recordsを諦めることでcondition typesも落ちる。これらを基盤となるR7RS実装とブリッジするのは単純に困難なので、これらを使用しているコードは何らかの方法で移植するしかない。R7RSは例外のraiseはR6RSのものをそのまま輸入しているが、例外に対するプレディケートがfile-error? / read-error?しか無いため、R6RSの提供するプレディケートは全く表現できない。
custom ポートは便利な機能だがyuniはそもそもcallbackを積極的に使っているのでportが必要なケースがあまり無い。副作用表現にport使う派の人には申し訳無いが。
eグループの望ましくない機能という分類も議論が有りそうだが、個人的にはidentifier-syntaxやsyntax-caseはR6RSでないschemeとの食べ合せが悪いので推奨できない。

APIデザインの難しさ

R6RSの語彙を久々に見返してみると、R6RSよりもR7RSの方が不味い語彙が相対的に多いように思える。R7RSの不味い語彙の多くは互換性の要求に起因する(char-ready?とか)。そういう意味では、R6RSは思いきり良く語彙を整理しているとも言えるが、コミュニティの受けは悪かったという歴史がある。
R7RSは、語彙のポリモーフィズムを強化する方向に持っていっている。R6RSは、新しい手続きのarityは基本的に固定であり、手続きに対して固定的な機能を割り当てる思想になっているように見える。個人的にはR6RSの方向性の方が良いと考えていて、yuniも必要の無い場合は可変長の手続きを避け、手続きを分割するようにしている。
APIとして見た場合、Schemeの語彙はあまり良いAPI界面を提供していないと言える - conditionやerror-objectにおけるmessageのようなユーザインタラクションを行うためのデータも直接的に公開しているため、例えばスクリプトは処理系の発生させるエラーをパースすることが可能になる - 当然、messageを多言語化するとそのようなスクリプトは良く動作しなくなる。

次の一手

R6RSとR7RSの標準シンボルを突き合わせて、ひとつひとつ比較していく。名称が同じシンボルであっても、R7RSがR6RSのスーパーセットになっていたり、その逆も多分あるので、それらの分類を行う。流石に、完全に互換性が無いのはbytevector-copy!くらいだと信じたいが。。