SECDV Schemeの実装 - listライブラリ

というわけで比較的退屈な標準ライブラリの実装作業....え?appendってリスト以外も返すの?

    ((r7c-basic lib lists)
     list?
     list append reverse
     memq
     assq assv
     make-list length list-tail list-ref list-set! list-copy)

(memvはcase構文で使ってるのでライブラリではなくcore scheme行き。)
今回からR7RS標準ライブラリのテストを揃えていくが、ついでに他の処理系、特にR6RSとR5RSに提供しているR7RS互換レイヤのテストも兼ねることにした(貧乏症)。これで、いくつかの処理系ではlist-copyが期待通り動作していないことに気付いたので実装を追加しておいた。

要するにr7cからのコピペになる。ちゃんとライブラリにして実装を1箇所にした方が美しいかもしれないが良い方法が思いあたらない。
テストに有るように、list-copyはリストでない物を受けたときにオブジェクト自体を返却する。また、非正規リスト(= リストの末尾がnilで終わらないリスト)をappendやlist-copyのような手続きに渡したときの挙動もR7RSでは規定されている。
appendは引数列の末尾を特別扱いする(appendに渡された最後の引数は返却するリストの一部になる)。この辺の挙動はSRFI-1譲り。

The resulting list is always newly allocated, except that it shares structure with the final list i argument. This last argument may be any value at all; an improper list results if it is not a proper list. All other arguments must be proper lists.

ただ、SRFI-1はlist-copyを

Copies the spine of the argument.

の1行で済ませているが、リファレンス実装は

(define (list-copy lis)
  (let recur ((lis lis))
    (if (pair? lis)
	(cons (car lis) (recur (cdr lis)))
	lis)))

と、R7RS期待通りの処理(非pairはそのまま、非正規リストは非正規リストにコピー)を実装している。
... listsはこんな感じで記事に書くことが有るけど、次のstringsとか何か書くこと有るんだろうか。。

  • stringsで実装すべき手続き:
    ((r7c-basic lib strings)
     string substring
     string-append string->list list->string
     string-copy string-copy! string-fill!
     make-string
     string=?
     string<? string>? string<=? string>=?)

stringの比較演算をどう書くかは微妙なポイントか。キレイな書き方が思いつかない。