やっとちょっとやる気が出てきたのでガリガリ進めてるですよ。でも凝り性 *など* (←重要)が災いして進行速度は人並以下ですよ。春休み中に終わるかしら。とりあえず本日の無駄時間:

((a b ...) ...)

というpatternに

((0 1) (2 3 4) (5) (6 7))

というのを食べさせたときのbの束縛を考える。順にmatchしていくに従って

(0        (1))
 ^aの部分 ^bの部分
(2 (3 4))
(5 ())
(6 (7))

とひとつずつsubform mappingが与えられて、それを最終的に

((a b)
 ((0 2 5 6)
  ((1) (3 4) () (7))
  ))

という並行listに収斂することになります。これを馬鹿正直に

step1: ((0 2) ((1) (3 4)))
step2: ((0 2 5) ((1) (3 4) ()))
step3: ((0 2 5 6) ((1) (3 4) () (7)))

としたのでは append 連打で遅く (O(n^2)に) なってしまうので却下です。List を前から作るといえば SigScheme では ScmQueue ですが、それを pattern variable の数だけ用意するのは無駄です。そこでよく使われる常套手段が逆向きに push していって reverse! ですが、最後の reverse! を map していくのも省略できまいかと思って一計を案じました。循環 list を作って尻尾だけ参照しておけば前から list を作りつつ、append は毎回 O(1) ではなかろうか、と。

step1: (#0=(2 0 . #0) #1=((1) (3 4) . #1))
step2: (#0=(5 0 2 . #0) #1=(() (1) (3 4) . #1))
step3: (#0=(6 0 2 5 . #0) #1=((7) (1) (3 4) () . #1))
step4: ((0 2 5 6) ((1) (3 4) () (7)))

で、大体できたあたりでちょっと効率計算をしてみました。Pattern variable の数を p, 一つの pattern variable あたりの chain の長さを nとすると、reverse! 戦略では memory access 回数は cell 一つあたり append 毎に push の為に一回 + slot 更新に一回、最後に reverse! で二回ずつなので合計 2np + 2np = 4np。循環list戦略では append あたり参照変更が二回 + slot 更新、最後に '() 付加、で合計 3np + p

うーむ、きわい…
;; Code complexity の増加と天秤に掛けるとさらに痛い。
1.5 倍速ぐらいの感覚で妄想してたんだが…

ちなみにどの方法でも space complexity は最小 (無駄な cell は一つも消費されず) です。結局 reverse! の code の再利用性を考えて循環 list は没に。

とかこんな調子でやってるから三ヶ月もかかるんだよな…