Ответ 1
Я не согласен, что код внутри 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]