Scheme修行 第19章 宝石泥棒(その2)
ここでは文字列解析のtokenizerの様な挙動が紹介されます。木構造のデータを与えると、その中の最も左に出現するアトムを返す。次に呼び出すと次ぎに左側のアトムを返す、と言った挙動です。極めて手続き的と言うか。アトムが見つかった時点で継続を使って脱出し、同じく継続を使って続きの処理に戻る動作を実装します。
ノート:
two-in-a-row
two-in-a-rowのおさらい。連続した要素を含んでいると言う述語。
> (let ((lat '(mozzarella cake mozzarella))) (two-in-a-row lat)) #f > (let ((lat '(mozzarella mozzarella pizza))) (two-in-a-row lat)) #t >
two-in-a-row*?
two-in-a-row*?は木構造データの括弧を全て取り払って一列に並んだアトムのリストにした時に連続した要素があると言う述語。
walk
walkは与えられた木の最も左のアトムを見つけると、それにleaveを適用する。leaveの定義はまだ不明
start-it
関数の先頭でletccしていて、その関数hereをleaveに設定している。なのでwalkの中でleaveを適用するとstart-itの関数値として戻る。
> (let ((l '((potato) (chips (chips (with))) fish))) (start-it l)) potato >
waddle、start-it2
waddleではleaveを適用する前にその場所をfillに保存しておく。後でfillを適用する事で続きの処理が行われる。
> (let ((l '((donuts) (cheerios (cheerios (spaghettios))) donuts))) (start-it2 l)) donuts > (fill) cheerios > (fill) cheerios > (fill) spaghettios > (fill) donuts > (fill) () >
get-next
waddleがleaveを適用するとget-nextの関数値として返る。
> (let ((l '((donuts) (cheerios (cheerios (spaghettios))) donuts))) (start-it2 l)) donuts > (get-next (quote go)) cheerios > (get-next (quote go)) cheerios > (get-next (quote go)) spaghettios > (get-next (quote go)) donuts > (get-next (quote go)) () >
> (let ((l '(donut))) (get-first l)) donut > (get-next (quote go)) () > (let ((l '(fish (chips)))) (get-first l)) fish > (get-next (quote go)) chips > (get-next (quote go)) () > (let ((l '(fish (chips) chips))) (get-first l)) fish > (get-next (quote go)) chips > (get-next (quote go)) chips >
全てを纏めたtwo-in-a-row*?の動作確認をする。
> (let ((l '(((food) ()) (((food)))))) (two-in-a-row*? l)) #t >