Chibi-Scheme の length* 手続き

SRFI-149 の実装例、 Chibi-Scheme の syntax-rules 構文の定義中に使われている length* 手続きは、 Chibi 独自のもので、 C 言語の関数 sexp_length_op を登録してあります。

./opcodes.c:156:_FN1(_I(SEXP_FIXNUM), SEXP_NULL, "length*", 0, sexp_length_op),

この syntax-rules 変換子による変換結果で使われる別名 _length は、 シンボル length* の別名であって、 length の別名ではありません。 そうでないと、 ドッテッド・リストのパターンを扱えなくなります。 length* ですけど、 名称と syntax-rules での使い方から予想するに、 正規リストとドッテッド・リストの両方のときペアの個数を数えてくれるのでしょう。 Chibi で試すとそうふるまいますし、 念のため sexp.c から sexp_length_op 関数を検めても確かにそうなっています。 循環リストでは偽を返します。 Scheme に直訳するとこう。

(define (length* ls)
 (if (not (pair? ls))
  0
  (let loop ((tortoise ls) (hair (cdr ls)) (res 1))
   (cond
    ((eq? tortoise hair) #f)
    ((and (pair? hair) (pair? (cdr hair)))
     (loop (cdr tortoise) (cddr hair) (+ res 2)))
    (else (if (pair? hair) (+ res 1) res))))))

(length* '1)                ;=> 0
(length* '(1))              ;=> 1
(length* '(1 . 2))          ;=> 1
(length* '(1 2))            ;=> 2
(length* '(1 2 . 3))        ;=> 2
(length* '(1 2 3))          ;=> 3
(length* '(1 2 3 . 4))      ;=> 3
(length* '(1 2 3 4))        ;=> 4
(length* '#0=(1 2 . #0#))   ;=> #f

それにしても、 独自手続きを SRFI で使うときは、 定義を書いておいて欲しいものです。