2

斯卡拉 2.10.2。跑步

import util.continuations._
import concurrent.ops._

object Main {
    def main(args: Array[String]) {
        reset {
            try {
                shift { cont: (Unit => Unit) => {
                    spawn {
                        throw new Exception("blah")
                        cont()
                    }
                }}
                println("after shift")
            } catch {
                case e: Exception => println(e)
            }
            println("reset end")
        }
    }
}

Cont.scala:16: error: type mismatch;
 found   : Unit
 required: Unit @scala.util.continuations.cpsParam[Unit,Unit]
                case e: Exception => println(e)
                                            ^
one error found

如果我删除 try/catch 块,一切都很好。我仍在试图弄清楚 Scala 中的延续是如何工作的,但这完全让我难以理解。

4

2 回答 2

1

只是说显而易见的 - 这是一个Scala 类型推断遇到 cps-annotation问题。catch 块不包含任何 cps 注释表达式。在这种情况下,catch-block 应该与 try-block 具有相同的类型:

Unit @cps[Unit] // same as Unit @cpsParam[Unit,Unit]

根据我的经验,Scala 中的类型推断和 CPS 转换并不总是按预期工作,并且在一个版本的 Scala 中工作的东西在另一个版本中不工作。

存在诸如Scala Continuations中提到的try_protector之类的解决方法- 为什么我的转移调用不能在 try-catch 块内?

不确定它是否对您有帮助(即 Scala 版本 2.10.2)。

于 2013-07-15T22:42:53.330 回答
0

您是否打算使用 try/catch 语句来捕捉Exception("blah")

即使它已编译,spawn在流程开始运行延续之前,它也会在另一个线程上发生。

没有 try/catch 你有这样的东西:

println("in main " + Thread.currentThread())
reset {
  shift { cont: (Unit => Unit) =>
    {
      spawn {
        println("in spawned " + Thread.currentThread())
        cont()
      }
    }
  }
  println("after shift " + Thread.currentThread())
  println("reset end")
}

}

cont函数是对应于该函数的代码的具体化部分:

val cont = () => {
  println("after shift " + Thread.currentThread())
  println("reset end")
}

所以当你这样做时spawn { cont() },你只需println在一个新的单独线程中运行这两个。运行程序,我得到:

in main Thread[main,5,main]
in spawned Thread[Thread-1,5,main]
after shift Thread[Thread-1,5,main]
reset end

这表明继续在单独的线程上运行。现在,如果您插入throw new Exception()before cont(),那么您得到的只是在生成的线程上抛出的异常(显然异常会被吞没)。

shift是否会在 try/catch 中运行延续并在您尝试执行的操作之后抛出异常?

reset {
  shift { cont: (Unit => Unit) =>
    spawn {
      println("in spawned " + Thread.currentThread())
      try { cont() }
      catch { case e: Exception => println(e) }
    }
  }
  println("after shift " + Thread.currentThread())
  throw new Exception("blah")
  println("reset end")
}

}

这打印:

in main Thread[main,5,main]
in spawned Thread[Thread-1,5,main]
after shift Thread[Thread-1,5,main]
java.lang.Exception: blah
于 2013-07-18T04:36:11.300 回答