BankersDequeで使用したmonolithic関数
BankersDqueでは、フロントとリアの2つのStreamを、以下のように操作してローテーション
を行っていました。
1. 長い方のStreamを全体の半分の長さだけ残す
– 残す方をtakeで取得
– 半分を超える部分をdropで作成
2. 半分を超える部分をreverseして短い方のstreamと結合
(これで2つのstreamが同じ長さになる)
– 半分を超える部分をreverse
– 短い方のリストを前にしてreverseした結果と++
Queueの場合はリアを空にしてフロントにすべて寄せていましたが、Dequeではフロントとリアの長さを同じ
にします。
|f| < |r| の場合:
val r’ = take (j, r)
val f’ = f ++ reverse (drop (j, r))
ここに登場したtake/drop/reverseの各関数は、4章で定義されたものです。
6.
Streamの実装(参考)
P36 の Figure4.1 より サスペンションを1つ潰すが、
新しいStreamのために構築したサスペンショ
ンで、後続の処理を遅延させる
fun lazy ($NIL) ++ t = t
| ($CONS (x, s)) ++ t = $CONS (x, s ++ t) incremental関数
fun lazy take (0, s) = $NIL
| take (n, $NIL) = $NIL
| take (n, $CONS (x, s)) = $CONS (x, take (n-1, s))
fun lazy drop (n, s) =
let fun drop’ (0, s) = s
| drop’ (n, $NIL) = $NIL
| drop’ (n, $CONS (x, s)) = drop’ (n-1, s)
in drop’ (n, s) end
fun lazy reverse s = monolithic関数
let fun reverse’ ($NIL, r) = r
| reverse’ ($CONS (x, s), r) = reverse’ (s, $CONS (x, r))
in reverse’ (s, $NIL) end
既存のサスペンションをすべて潰しながら、
新たなStreamを終端から構築する
スケジュールの導入
ローテーション実行中にrotateDrop関数と rotateRev関数が作成したサスペンションを、
次回のローテーション開始までに全て実行しなければなりません。
このためにスケジュールを導入します。
type ‘a queue = int * ‘a Stream * ‘a Stream (* front *)
* int * ‘a Stream * ‘a Stream (* rear *)
データサイズ データ スケジュール
ローテーションで新しいフロントとリアができるので、そのままスケジュールとします。
let j = (lenf + lenr) / 2; let i = lenf + lenr –j;
let r' = S.take (j, r); let f' = rotateDrop (f, j, r)
in (i, f', f', j, r', r')
Streamを順に開いていくことでサスペンションを実行します。
fun exec1 ($CONS (x, s)) = s
| exec1 s = s
おまけ: Global Rebuildingとの違い
だいたいこんな感じだと思います。
• Global Rebuildingには必要だったローテーション用のコピーが、Lazy Rebuildingで
は不要。
• Global Rebuildingを使用したHood MelvilleQueueでは、ローテーションに必要な処
理が比較的均等に分散していたが、Lazy Rebuildingを使用したRealTimeDequeで
は、短い方のStreamを再作成する$CONSだけを使ってdropやreverse遅延させて
いるので、サスペンションの実行コストに偏りがある。
19.
参考文献
• Chris Okasaki, “8.4.3 Real-Time Deque”, Purely Functional Data Structures,
Cambridge University Press (1999)
• Chris Okasaki, “Simple and efficient purely functional queues and deques”, Journal
of Functional Programming, 5(4):583-592, October 1995