A light weight Scala fork join syntax

China☆狼群 提交于 2019-12-05 21:22:38

Eric Torreborre wrote in the link provided by @retronym:

trait LazyParameters { 
  /** transform a value to a zero-arg function returning that value */ 
  implicit def toLazyParameter[T](value: =>T) = new LazyParameter(() => value) 
  /** class holding a value to be evaluated lazily */ 
  class LazyParameter[T](value: ()=>T) { 
    lazy val v = value() 
    def apply() = v 
  } 
} 

Here's LazyParameter version of your test:

object ForkTest2 extends LazyParameters {

...

def forkAll(fx1: LazyParameter[Any]*): List[Any] = {
  val results = fx1.toList.map {
    fx: LazyParameter[Any] => Futures.future(fx.apply())}
  Futures.awaitAll(tenMinutes, results: _*)
}

Edit: As you've noticed, implicit evaluates the by-name parameter and it doesn't carry forward the evaluation delay. Why not just use the word future? I personally think it makes the code more readable.

import actors.Futures
import actors.Futures.future
import actors.Future

...

def test2 {
  val results = forkAll(
    future {
      Thread.sleep(500)
      println("inside fx1 ",+System.currentTimeMillis)
      true
    },
    future {
      Thread.sleep(1000)
      println("inside fx2 ",+System.currentTimeMillis)
      "stringResult"
    },
    future {
      Thread.sleep(1500)
      println("inside fx3 ",+System.currentTimeMillis)
      1
    },
    future {
      Thread.sleep(2000)
      println("inside fx4 ",+System.currentTimeMillis)
      1.023
    })

  println(results)
  true
}

...

def forkAll(futures: Future[Any]*): List[Any] = {
  println("forkAll")
  Futures.awaitAll(tenMinutes, futures: _*)
}

You can't use call-by-name types as a repeated parameter (aka varargs), thanks to this bug: https://lampsvn.epfl.ch/trac/scala/ticket/237

See recent discussion here: http://old.nabble.com/Lazy-varargs-td27169264.html

A sample implementation for anyone interested,

For use case that with a few function argument, may be just define list of fork function with different number of arguments (following the idea in tuple definition) and enjoy type safe return type

object ForkTest4 extends LazyParameters {
  def main(args: Array[String]) {
    test4
  }

  def test4 {
    println("Begin test 4")
    //Without the explicit call to type conversion would cause early evaluation
    //    val result4 = forkAll({
    val result4 = forkAll(l {
      Thread.sleep(500)
      println("inside fx4 ", +System.currentTimeMillis)
      true
    })
    println(result4)
    true
  }

  val tenMinutes = 1000 * 60 * 10

  def forkAll(fx1: (() => Any)*): List[Any] = {

    val results = fx1.toList.map {

      fx: (() => Any) => {

        val result = Futures.future(fx.apply())

        result
      }
    }
    Futures.awaitAll(tenMinutes, results: _*)
  }

  def l[T](t: => T): (() => T) = () => t

  implicit def implicitLazy[T](t: => T): (() => T) = () => t
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!