リスト 19.10 最適化された関数型待ち行列
class Queue[+T] private (
private[this] var leading: List[T],
private[this] var trailing: List[T]
) {
private def mirror() =
if (leading.isEmpty) {
while (trailing.isEmpty) {
leading =trailing.head::leading
tariling=trailing.tail
}
}
def head: T= {
mirror()
leading.head
}
def tail:Queue[T] = {
mirror()
new Queue(leading.tail,trailing)
}
def enqueue[U >: T](x: U) =
new Queue[U] (leading,x :: trailing)
}
head操作が繰り返されても、tailingからleadingへのコピーは高々1度しか行われない。
mirrorにより、leadingとtailingは中身が変化しているから。
ちなみに、リスト19.1のほうは、leadingもtrailingもvalのため、
def head = mirror.leading.headが、連続してもその都度、
def mirror = if (leading.isEmpty) new Queue(trailing.reverse,Nil) else this
が行われてしまうらしい。このとき、leading.isEmpty=trueなら、その都度tailing.reverseが
おこなわれてしまうということらしい。(def headでは、新たなQueueを返してもいないため、もとのleadingが変化しないから)
以下の
while (!trailing.isEmpty) {
leading =trailing.head::leading
tariling=trailing.tail
}
の部分は、leadingが空のときのみ行われる。
trailingが空になるまで、trailingのtailが新たにtailingとなり
trailingのheadが、leadingの先頭に追加されている。つまり、反転されてleadingに移動している。
************
ここまで読んで、scalaの実行速度を落とさないようにするには、けっこう気を付けていく
必要があるのだと感じた。
0 件のコメント:
コメントを投稿