Я не согласен, что код в reset
мертв без shift
.На самом деле reset
просто определяет границы продолжения (потому что они называются продолжениями с разделителями). Код будет мертв, если у вас есть shift
где-то в пределах reset
и вы не вызываете функцию продолжения,Например:
reset {
println(1)
shift((k: Unit => Unit) => println(2))
println(3)
}
Код после shift
мертв (println(3)
), потому что я не позвонил k(Unit)
.
С другой стороны, кажется, что reset
ожидает некоторый специальный тип возврата от своего тела - тот, который аннотирован @cpsParam
аннотацией.Вы можете проверить определение метода reset
:
def reset[A,C](ctx: => (A @cpsParam[A,C])): C = ...
И shift
производит только то, что ожидает метод reset
.Вот определение метода shift
:
def shift[A,B,C](fun: (A => B) => C): A @cpsParam[B,C] = ...
Но вы все равно можете использовать reset
без вызова shift
внутри него.Этот трюк сделает это:
def foo[T](body: => T @cps[Any]) = reset(body)
foo {
println("it works")
}
Обратите внимание, что @cps
это просто псевдоним типа для @cpsParam
.Вот это определение:
type cps[A] = cpsParam[A, A]