2013-07-15 4 views
2

Scala 2.10.2. ЗапускОбработка исключений вокруг сдвига в Scala

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 

Если я удалить попробовать/поймать блок все в порядке. Я все еще пытаюсь понять, как продолжаются работы в Scala, но это полностью ускользает от меня.

ответ

1

Просто заявка очевидна - это Вывод типа Scala соответствует cps-аннотациям проблема. Блок catch не содержит аннотированного выражения cps. В этом случае улов-блок, как ожидается, будет того же типа, что и примерки блока:

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

К моему опыту, типа логического вывода и CPS-преобразование в Scala не всегда работает, как ожидалось, и вещи, которые работают в одной версии Scala, не работают в другой версии.

Там существует обходные пути, такие как try_protector упоминается в Scala Continuations - Why can't my shifted call be inside a try-catch block?

Не уверен, если это поможет в вашем случае (т.е. Scala версии 2.10.2).

0

Вы намерены использовать инструкцию try/catch для улова Exception("blah")?

Даже если он скомпилирован, spawn, который устарел, будет происходить в другом потоке, прежде чем поток начнет выполнение продолжения.

Без TRY/улова у вас есть что-то вроде этого:

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() до cont(), тогда все, что вы получаете, является исключением, созданным на порожденной нити (где, по-видимому, исключение будет проглочено).

Будет ли продолжение продолжения внутри try/catch и исключение, возникшее после того, как shift будет больше того, что вы пытаетесь сделать?

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