Scala Continuations-почему мой смещенный вызов не может быть внутри блока try-catch?
Я новичок в продолжениях Scala и относительно новичок в языке scala вообще.
Я попробовал поиграть с продолжениями Scala и написал следующий код: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
Я понимаю, что есть проблема с "впрыскиванием" исключения в продолжение, но почему я не могу просто поместить смещенный вызов внутри блока try-catch?
Мне это нужно в рамках, которые я планирую, в которых программист не будет знать, что его код используется в форме продолжения (он вызовет некоторую функцию, которую он будет считать "нормальной", но на самом деле сделает shift
).
Можно ли решить эту проблему с помощью ControlContext ? Поможет ли это, если я добавлю некоторые правила "ввода" значений (возможно, с помощью @cps[..] )?
Я уже думал об альтернативе использования актеров, так что вы не получите никакого кредита за это:)
Спасибо,
(P. S. Я в Scala 2.9.2, и, очевидно, использовать -П:продолжения:включить флаг)
1 ответ:
Спасибо @som-snytt,но ваше решение было несколько далеким от общего. Я не могу требовать от пользователя фреймворка писать
Тем не менее, я поиграл с вашим решением и построил следующий код:def my_check
вместоval my_check
каждый раз, когда он использует блок try-catch.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-catch с помощью
try_protector
, и код будет компилироваться.Не спрашивайте меня, как или почему... Похоже на компиляцию вуду в мне...
Я не пробовал его на scala 2.10.