Требует ли «сброс» «сдвига» внутри блока? - PullRequest
11 голосов
/ 15 мая 2011

Правильно ли, что reset требует shift внутри блока? Я попробовал это и получил следующее:

scala> reset {} 
error: cannot cps-transform expression (): type arguments [Unit,Unit,Nothing]
do not conform to method shiftUnit's type parameter bounds [A,B,C >: B]

Это выглядит разумно (поскольку блок reset без shift внутри является "мертвым кодом", который никогда не выполняется), но я не понимаю ошибки.

Каков точный смысл сообщения об ошибке?

1 Ответ

4 голосов
/ 27 мая 2011

Я не согласен, что код в 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]
...