我是Scala延续的新手,对scala语言来说相对较新。
我尝试使用Scala continuation并编写以下代码:
case class MyException(msg:String) extends Exception
def go:Int = reset {
println("enter your input")
val my_check = //try
{
val user_input = readLine()
if (!user_input.matches("\\w+")) {
throw new MyException("illegal string: " + user_input)
}
shift {
k: (Boolean => Int) => {
if (user_input == "true") {
k(true)
}
else if (user_input == "false") {
k(false)
}
else {
// don't even continue
0
}
}
}
}
// catch {
// case MyException(msg) => false
// }
if (my_check) {
println("TRUE")
1
}
else {
println("FALSE")
-1
}
}
println(go)
代码按预期工作:当用户输入非字母数字字符串时,抛出MyException
,当用户输入“true”时,代码继续my_check = true
,当用户输入“false”时“代码继续my_check = false
,当用户输入不是”true“或”false“的字母数字字符串时,go
函数将以0退出。
然后我尝试将一些代码包装在try-catch块(注释所在的位置)中,并且编译失败了:
错误:在非cps位置找到cps表达式
val my_check =尝试
我理解将一个异常“注入”到一个延续中有一个问题,但为什么我不能简单地将转移的调用放在try-catch块中?
我在我计划的框架中需要这个,程序员不会意识到他的代码是以延续形式使用的(他会调用一些他认为是“正常”的函数,但是会实际上做shift
)。
显然,我需要他能够在try-catch块中调用该函数,即使移位的调用本身不会引发异常。
ControlContext可以解决此问题吗? 如果我在值上添加一些“输入”规则(可能使用 @cps [..] )会有帮助吗?
我已经考虑过使用Actors的替代方案,因此你不会得到任何荣誉:)
谢谢,
(P.S。我正在使用Scala 2.9.2,显然使用 -P:continuations:enable 标志)
答案 0 :(得分:0)
谢谢@ som-snytt,但你的解决方案与通用解决方案有些差距。每次使用try-catch块时,我都不能要求框架用户编写def my_check
而不是val my_check
。
但是,我使用了您的解决方案,并构建了以下代码:
import scala.util.continuations._
case class MyException(msg:String) extends Exception
object try_protector {
def apply[A,B](comp: => A @cps[B]):A @cps[B] = {
comp
}
}
object Test extends App {
def go: Int = reset {
println("enter your input")
val my_check = try_protector {
try {
val user_input = readLine()
if (!user_input.matches("\\w+")) {
throw new MyException("illegal string: " + user_input)
}
shift {
k: (Boolean => Int) => {
user_input match {
case "true" => k(true)
case "false" => k(false)
case _ => 0
}
}
}
} catch {
case MyException(msg) => false
}
}
if (my_check) {
println("TRUE")
1
} else {
println("FALSE")
-1
}
}
println(go)
}
它有效! (关于scala 2.9.2)
用户只需用try_protector
包装他的try-catch块,代码就会编译。
不要问我怎么或为什么......看起来像编辑VODOU给我......
我没有在scala 2.10上尝试过。