2015年6月13日土曜日

scala関数型デザイン&プログラミング P131

Exercise7.3 map2を修正し、Futureのタイムアウトの規約に従うようにせよ。

javaをよく理解してなこともあり、コードを読み取るのが難しい。
Map2Futureの中にある@volatileは、「あるスレッドで更新された値が別スレッドで読み込まれる」ことが保証されるのだそうだ。
chache.isDefinedはOption[C]のcacheがSomeかNoneかを表す。
afの評価にかかった時間を記録し、bfの評価に割り当てられた時間からその時間を引くという操作が、val br = b.get(timeoutMs - at, TimeUnit.MILLISECONDS)の部分か?

def map2[A,B,C](a: Par[A], b: Par[B])(f: (A,B) => C): Par[C] =
  es => {
    val (af, bf) = (a(es), b(es))
    Map2Future(af, bf, f)
  }

case class Map2Future[A,B,C](a: Future[A], b: Future[B],
                             f: (A,B) => C) extends Future[C] {
  @volatile var cache: Option[C] = None
  def isDone = cache.isDefined
  def isCancelled = a.isCancelled || b.isCancelled
  def cancel(evenIfRunning: Boolean) =
    a.cancel(evenIfRunning) || b.cancel(evenIfRunning)
  def get = compute(Long.MaxValue)
  def get(timeout: Long, units: TimeUnit): C =
    compute(TimeUnit.MILLISECONDS.convert(timeout, units))

  private def compute(timeoutMs: Long): C = cache match {
    case Some(c) => c
    case None =>
      val start = System.currentTimeMillis
      val ar = a.get(timeoutMs, TimeUnit.MILLISECONDS)
      val stop = System.currentTimeMillis; val at = stop-start
      val br = b.get(timeoutMs - at, TimeUnit.MILLISECONDS)
      val ret = f(ar, br)
      cache = Some(ret)
      ret
  }
}


Exercise7.4 lazyUnitを使って関数を記述せよ。この関数は任意の関数A=>Bから、その結果を非同期で評価する関数へと変換する。

def asyncF[A,B](f:A=>B):A=>Par[B]=
  a => lazyUnit(f(a))

0 件のコメント:

コメントを投稿