というわけでSchemeの基本要素だけで実装できるものは一通り実装を終えてテストも書いた。

... 本当に書くことが無いな。。ライブラリを他所からパチって来ずに自前で実装しているのは、ゲームに組込むのにパブリックドメインなランタイムが欲しいため。expanderはゲームの実行時は不要なのでAlexpanderを使い続けているけど、ランタイム側は組込まれてしまうのでライセンスの制約を受ける。

strings https://github.com/okuoku/yuni/blob/d759e40bd57dd2eabdc19271b8735837e5b0c088/lib-r7c/r7c-basic/lib/strings.sls stringsライブラリ。string-append等。

https://github.com/okuoku/yuni/blob/d759e40bd57dd2eabdc19271b8735837e5b0c088/tests/vm/vmtest4.sps#L142 テスト類

stringsライブラリはScheme上で実装するのには向いてない気がする。今回の実装はO(1)文字列アクセスを強く期待しており、基本的には文字列は 長さを決定してmake-stringで確保 → string-set! で文字を一つ一つセット という方式で実装している。

今回で言うと、BASICやGame Makerのようなベースになるランタイムが存在する環境では、その環境の文字列がO(1)アクセス可能という保証は無いので、あまりパフォーマンスが出ない危険がある。また、Scheme処理系でも rope 構造を文字列に採用していたり(Picrin等)、UTF-8な内部表現を直接利用する処理系(Chibi-scheme等)もあるため打率は悪い。ちなみにR6RSはO(1)文字列アクセスを要求しているが、R7RSは特に要求していない。 http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_sec_11.12 ‌ Implementors should make string-ref run in constant time. chibi-schemeは文字列を実際の文字列と文字列カーソルに分けている。UTF-8のような構造を採用すると、string-refの実装のためには文字の位置と実際のバイト位置の対応を適切に管理する必要があるが、適当な時間文字列カーソルをキャッシュするのは悪くないアイデアかもしれない。

vectorやbytevectorと異なり、文字列は比較演算を実装する必要がある。...これをどうやってエレガントに実装するかというのは悩みどころだが、考えてる時間は無いので "あいこ" だったら次の文字を比較する https://github.com/okuoku/yuni/blob/d759e40bd57dd2eabdc19271b8735837e5b0c088/lib-r7c/r7c-basic/lib/strings.sls#L44 そうでないケースは比較して試合終了 https://github.com/okuoku/yuni/blob/d759e40bd57dd2eabdc19271b8735837e5b0c088/lib-r7c/r7c-basic/lib/strings.sls#L46 最終文字であいこを勝たせるかどうかはフラグで渡す https://github.com/okuoku/yuni/blob/d759e40bd57dd2eabdc19271b8735837e5b0c088/lib-r7c/r7c-basic/lib/strings.sls#L32 ゼロ文字ケースは特別扱いする フラグ引数の数をケチするために、等長文字列の比較と長さが違う文字列の比較は分ける で実装してみた。実は最初"あいこ"ケース以外では次に行く必要が無いことを見落していて、えらい複雑な条件を書いていた。

まぁ速度的に不満が出てきたらちゃんと実装するということで。。今は正確に動くことの方がずっと重要。

vectors https://github.com/okuoku/yuni/blob/d759e40bd57dd2eabdc19271b8735837e5b0c088/lib-r7c/r7c-basic/lib/vectors.sls vectorsライブラリ。

https://github.com/okuoku/yuni/blob/d759e40bd57dd2eabdc19271b8735837e5b0c088/tests/vm/vmtest4.sps#L245 テスト類

特記事項なし！

実は、string→vector系をstringsライブラリに入れるかどうかはちょっと悩んだ。たぶんvectorsライブラリにstring→vector類を入れたのは間違いで、vectorはpair等同様Scheme固有のデータ型で、どちらかというとベースランタイムの性質が出やすいstringsに実装を集中させた方が再利用性の面では有利なのではないか。

vectorsに限らず、indexの算術演算には専用のfixnumライブラリを使用している($fx=とか$fx+など)。R7RSでは、これらのインデックスを表わす数値は必ず正確数を使うことを求めているのと、完全なnumeric towerをScheme側を使って実装する必要が有る場合に依存関係の循環が出ないようにするため。

bytevectors https://github.com/okuoku/yuni/blob/d759e40bd57dd2eabdc19271b8735837e5b0c088/lib-r7c/r7c-basic/lib/bytevectors.sls bytevectorsライブラリ。

https://github.com/okuoku/yuni/blob/d759e40bd57dd2eabdc19271b8735837e5b0c088/tests/vm/vmtest4.sps#L305 テスト類

ほぼvectorsのコピペ！

最大の問題はutf8→stringとstring→utf8で、これだけのために乗除算(またはビット演算)が必要というアンバランスぶり。というわけで未実装(ASCIIだけ)。

R7RS smallでは、R6RSに見られたようなu8-list→bytevectorに相当するようなコンストラクタは無い。実際にはbytevector手続きへのapplyという形で同じ処理が可能だが。。