Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Scala@suspendable方法转换为未来方法_Scala_Continuations - Fatal编程技术网

将Scala@suspendable方法转换为未来方法

将Scala@suspendable方法转换为未来方法,scala,continuations,Scala,Continuations,假设我有一个睡眠功能: def sleep(delay:Int) : Unit @suspendable = { .... } 是否可能有一个函数future来创建一个异步版本的sleep函数,该函数可以被同步地等待 def future(targetFunc: (Int => Unit @suspendable)) : (Int => Future) = { .... } class Future { def await : Unit @suspendable

假设我有一个睡眠功能:

def sleep(delay:Int) : Unit @suspendable = {
  ....
}
是否可能有一个函数future来创建一个异步版本的sleep函数,该函数可以被同步地等待

def future(targetFunc: (Int => Unit @suspendable)) : (Int => Future) = {
    ....
}

class Future {
  def await : Unit @suspendable = {
     ....
  }
}
您应该能够执行以下操作:

reset {
  val sleepAsync = future(sleep)
  val future1 = sleepAsync(2000)
  val future2 = sleepAsync(3000)
  future1.await
  future2.await
  /* finishes after a delay of 3000 */
}
对sleepAsync的两个调用应显示为立即返回,对Future#await的两个调用应显示为阻塞。当然,它们都是在reset结束时掉下来的,之后的代码负责在延迟后调用continuation

否则,有没有其他方法可以并行运行两个@suspendable函数并等待它们都完成


我有一个可编辑的要点,其中有我想做的事情的框架:

我不确定我是否完全理解这个问题,但这里有一个尝试:

import scala.util.continuations._

class Future(thread: Thread) {
  def await = thread.join
}

object Future {

  def sleep(delay: Long) = Thread.sleep(delay)

  def future[A,B](f: A => B) = (a: A) => shift { k: (Future => Unit) =>
    val thread = new Thread { override def run() { f(a) } }
    thread.start()

    k(new Future(thread))
  }

  def main(args:Array[String]) = reset {
    val sleepAsync = future(sleep)
    val future1 = sleepAsync(2000) // returns right away
    val future2 = sleepAsync(3000) // returns right away
    future1.await // returns after two seconds
    future2.await // returns after an additional one second
    // finished after a total delay of three seconds
  }
}
在这里,
Future
实例只不过是
线程
上的一个句柄,因此您可以使用它的
join
方法阻止它,直到它完成为止

future
函数接受类型为
a=>B
的函数,并返回一个函数,当提供
a
时,该函数将启动一个线程来运行“futured”函数,并将其包装在
future
中,该函数被注入到延续中,从而将其分配给
val future1

这和你想要的接近吗

object Forks {

  import scala.util.continuations._

  case class Forker(forks: Vector[() => Unit @suspendable]) {
    def ~(block: => Unit @suspendable): Forker = Forker(forks :+ (() => block))
    def joinIf(pred: Int => Boolean): Unit @suspendable = shift { k: (Unit => Unit) =>
      val counter = new java.util.concurrent.atomic.AtomicInteger(forks.size)
      forks foreach { f =>
        reset {
          f()
          if (pred(counter.decrementAndGet)) k()
        }
      }
    }
    def joinAll() = joinIf(_ == 0)
    def joinAny() = joinIf(_ == forks.size - 1)
  }

  def fork(block: => Unit @suspendable): Forker = Forker(Vector(() => block))
}
使用fork(),我们现在可以等待许多“suspendables”。使用~()将可悬挂项链接在一起。使用joinAll()等待所有的可挂起项,使用joinAny()只等待一个可挂起项。使用joinIf()自定义联接策略

object Tests extends App {

  import java.util.{Timer, TimerTask}
  import scala.util.continuations._

  implicit val timer = new Timer

  def sleep(ms: Int)(implicit timer: Timer): Unit @suspendable = {
    shift { k: (Unit => Unit) =>
      timer.schedule(new TimerTask {
        def run = k()
      }, ms)
    }
  }

  import Forks._

  reset {
    fork {
      println("sleeping for 2000 ms")
      sleep(2000)
      println("slept for 2000 ms")
    } ~ {
      println("sleeping for 4000 ms")
      sleep(4000)
      println("slept for 4000 ms")
    } joinAll()
    println("and we are done")
  }
  println("outside reset")
  readLine
  timer.cancel
}
这就是输出。程序在时间T开始:

sleeping for 2000 ms
sleeping for 4000 ms
outside reset         <<<<<< T + 0 second
slept for 2000 ms     <<<<<< T + 2 seconds
slept for 4000 ms     <<<<<< T + 4 seconds
and we are done       <<<<<< T + 4 seconds
睡眠2000毫秒
睡眠4000毫秒

在《重置》之外,我写了这样一句话:这似乎可行,但似乎相当复杂。我觉得我可能错过了一种更简单的方法。我还发现:哪种方法似乎做得更好。你喜欢“获胜”的答案吗?我需要颁发赏金奖。你可以随心所欲地运行continuations,但不知何故,它们需要运行当前线程(否则总运行时间将是5000毫秒而不是3000毫秒)。实际上,您可能会使用线程池,而不是创建自己的
thread
实例。您希望如何运行
future1
future2
?啊。我希望将来能够使用一个可挂起的函数,而不是一个正常的函数。我现在把自己弄糊涂了。为什么
future
的目的不是获取一个不可挂起的函数并创建一个延续,以便在继续其余代码时可以挂起该函数?我认为这是为了让您可以并行运行而不是按顺序运行。例如,如果您有:
resp1=http.get”http://foo";     resp2=http.get“http://bar“
它们当前正在按顺序运行,但您可能不需要按顺序运行,而是希望它们并行运行,这样您就可以执行
resp1Future=http.get”http://foo";     resp2Future=http.get“http://bar";      resp1=resp1Future.get;resp2=resp2Future.get