4

私は 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)

コードは期待どおりに機能しました。ユーザーが英数字以外の文字列を入力すると aMyExceptionがスローされ、ユーザーが「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[..]を使用)?

アクターを使用する別の方法についてはすでに考えているので、それに対するクレジットは得られません :)

ありがとう、

(PS 私は Scala 2.9.2 を使用しており、明らかに-P:continuations:enableフラグを使用しています)

4

1 に答える 1

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-catch ブロックを でラップするだけtry_protectorで、コードがコンパイルされます。

方法や理由は聞かないでください...私にはVODOUのコンパイルのように見えます...

scala 2.10 では試していません。

于 2012-10-04T03:05:18.370 に答える