Scala连续 - 为什么我的转移呼叫不能在try-catch块中? [英] Scala Continuations - Why can't my shifted call be inside a try-catch block?

查看:186
本文介绍了Scala连续 - 为什么我的转移呼叫不能在try-catch块中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我尝试使用Scala连续播放,并写下了以下代码: p>

  case class MyException(msg:String)extends异常

def go:Int = reset {
println(输入你的输入)
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 {
//甚至不继续
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


我知道有一个问题是注入一个例外到一个延续,bu t为什么我不能简单地把转移的电话放在try-catch块中?



我在规划的框架中需要这个,程序员不会意识到他的代码以连续的形式使用(他会调用一些函数他认为正常,但实际上会执行 shift )。



显然,我需要他能够调用try-catch块中的函数,即使转移的调用本身也不会引发异常。



可以通过 ControlContext
如果我在值上添加了一些打字规则(可能是使用 @cps [..] ),那么它会有帮助吗?



<我已经考虑过使用演员的选择,所以你不会得到任何信用的:)



谢谢,



(PS我正在使用Scala 2.9.2,显然使用 -P:继续:启用标志)

解决方案

谢谢@ som-snytt,但是你的解决方案与一般的解决方案有所不同。我不能要求框架用户在每次使用try-catch时写入 def my_check 而不是 val my_check



但是,我使用您的解决方案,并构建了以下代码:

 code> import scala.util.continuations._ 

case class MyException(msg:String)extends异常

对象try_protector {
def apply [A ,B](comp:=> A @cps [B]):A @cps [B] = {
comp
}
}

对象测试扩展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 {
casetrue=> k(true)
casefalse=> 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上尝试过。


I'm new to Scala continuations, and relatively new to the scala language in general.

I tried playing with Scala continuations and wrote the following code:

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)

The code worked as expected: when the user enters a non-alphanumeric string a MyException is thrown, when the user enters "true" the code continues with my_check = true, when the user enters "false" the code continues with my_check = false, and when the user enters an alphanumeric string which is not "true" nor "false" the go function exits with 0.

Then I tried wrapping some of the code in a try-catch block (where the comments are), and the compilation failed with:

error: found cps expression in non-cps position

val my_check = try

I understand there's a problem with "injecting" an exception into a continuation, but why can't I simply put the shifted call inside a try-catch block?

I need this in the framework I'm planning, in which the programmer will not be aware that his code is used in a continuation form (he'll call some function which he would think to be "normal", but will actually do the shift).

Obviously, I need him to be able to call the function inside a try-catch block, even though the shifted call itself will not raise an exception.

Can this issue be solved with ControlContext? Will it help if I add some "typing" rules on the values (maybe with the @cps[..])?

I already thought about the alternative of using Actors so you won't get any credit for that :)

Thanks,

(P.S. I'm using Scala 2.9.2, and obviously use the -P:continuations:enable flag)

解决方案

Thanks @som-snytt, but your solution was somewhat far from a generic one. I can't demand the framework user to write def my_check instead of val my_check every time it uses a try-catch block.

However, I played with your solution, and built the following code:

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)
}

And it works! (on scala 2.9.2)

The user just has to wrap his try-catch block with a try_protector and the code will compile.

Don't ask me how or why... It looks like compilation VODOU to me...

I haven't tried it on scala 2.10.

这篇关于Scala连续 - 为什么我的转移呼叫不能在try-catch块中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆