"重置"是否需要在块内"移位"?

Mic*_*ael 11 continuations scala

它是正确的,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内部的块是"死代码",它永远不会执行)但我不明白错误.

错误消息的确切含义是什么?

ten*_*shi 5

我不同意,里面的代码reset没有shift. 实际上reset只是定义了延续的边界(那是因为它们被称为分隔shift延续)。如果您在其中的某个地方reset并且不调用延续函数,则代码将是死的。例如:

reset {
  println(1)
  shift((k: Unit => Unit) => println(2))
  println(3)
}
Run Code Online (Sandbox Code Playgroud)

之后的代码shift是dead( println(3)),因为我没有调用k(Unit)

另一方面,似乎reset期望从它的主体中得到一些特殊的返回类型 - 用注释进行注释的类型@cpsParam。您可以检查reset方法的定义:

def reset[A,C](ctx: => (A @cpsParam[A,C])): C = ...
Run Code Online (Sandbox Code Playgroud)

shift产生reset方法所期望的结果。这是shift方法的定义:

def shift[A,B,C](fun: (A => B) => C): A @cpsParam[B,C] = ...
Run Code Online (Sandbox Code Playgroud)

但您仍然可以使用reset而不需要shift在其中调用。这个技巧就可以做到:

def foo[T](body: => T @cps[Any]) = reset(body)

foo {
  println("it works")
}
Run Code Online (Sandbox Code Playgroud)

请注意,这@cps只是 的类型别名@cpsParam。这是它的定义:

type cps[A] = cpsParam[A, A]
Run Code Online (Sandbox Code Playgroud)