2014年12月14日日曜日

scalaスケーラブルプログラミング P374

リスト 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 件のコメント:

コメントを投稿