是否可以从以下代码中删除某些类型:
import util.continuations._
object TrackingTest extends App {
implicit def trackable(x: Int) = new {
def tracked[R] = shift { cf: (Int => (R, Set[Int])) =>
cf(x) match {
case (r, ints) => (r, ints + x)
}
}
}
def track[R](body: => R @cpsParam[(R, Set[Int]), (R, Set[Int])]) = reset {
(body, Set[Int]())
}
val result = track(7.tracked[Int] + 35.tracked[Int])
assert(result == (42, Set(7, 35)))
val differentTypes = track(9.tracked[String].toString)
assert(differentTypes == ("9", Set(9)))
}
track
功能会跟踪tracked
个实例Int
的来电(例如7.tracked
)。
是否可以在tracked
隐式推断类型参数,因此以下内容将编译:
track(7.tracked + 35.tracked)
答案 0 :(得分:2)
你的问题让我想到了延续如何追踪状态。所以我根据你的情况调整了这个并提出了这个:
import util.continuations._
object TrackingTest extends App {
type State = Set[Int]
type ST = State => State
implicit class Tracked(val i: Int) extends AnyVal {
def tracked = shift{ (k: Int=>ST) => (state:State) => k(i)(state + i) }
}
def track[A](thunk: => A@cps[ST]): (A, State) = {
var result: A = null.asInstanceOf[A]
val finalSate = (reset {
result = thunk
(state:State) => state
}).apply(Set[Int]())
(result, finalSate)
}
val result = track(7.tracked + 35.tracked)
assert(result == (42, Set(7, 35)))
val differentTypes = track(9.tracked.toString)
assert(differentTypes == ("9", Set(9)))
}
这是使用2.10.1,但如果用以下内容替换2.10.x隐式值类,它也适用于2.9.1
implicit def tracked(i: Int) = new {
def tracked = shift{ (k: Int=>ST) => (state:State) => k(i)(state + i) }
}
我做的主要更改是让tracked
不使用任何类型推断,修复为Int@cps[ST]
。然后,CPS插件会根据需要将计算映射到正确的类型(如String@cps[ST]
)。状态由继续返回一个State=>State
函数,该函数接受当前状态(一组整数)并返回下一个状态。复位的返回类型是一个从状态到状态(类型为ST
)的函数,它将采用初始状态并返回最终状态。
最后一招是使用var来捕获结果,同时保持reset
的预期类型。
答案 1 :(得分:1)
虽然这个问题的确切答案只能由编译器的作者给出,但我们可以通过查看continuation插件源代码来猜测它是不可能的。
如果您查看延续的来源,可以看到:
val anfPhase = new SelectiveANFTransform() {
val global = SelectiveCPSPlugin.this.global
val runsAfter = List("pickler")
}
val cpsPhase = new SelectiveCPSTransform() {
val global = SelectiveCPSPlugin.this.global
val runsAfter = List("selectiveanf")
}
anfPhase阶段在pickler阶段之后执行,而cpsPhase在selectiveAnf之后执行。如果你看SelectiveANFTransform.scala
abstract class SelectiveANFTransform extends PluginComponent with Transform with
TypingTransformers with CPSUtils {
// inherits abstract value `global' and class `Phase' from Transform
import global._ // the global environment
import definitions._ // standard classes and methods
import typer.atOwner // methods to type trees
/** the following two members override abstract members in Transform */
val phaseName: String = "selectiveanf"
如果我们使用scalac -Xshow-phases,我们可以看到编译过程中的阶段:
parser
namer
packageobjects
typer
superaccessors
pickler
refchecks
selectiveanf
liftcode
selectivecps
uncurry
......
正如您所看到的,在selectiveAnf和selectiveCps阶段之前应用了typer阶段。应该确认类型推断发生在typer阶段,但如果确实如此并且它是有意义的,现在应该清楚为什么你不能省略7.tracked和35.tracked上的Int类型。 / p>
现在,如果您还不满意,您应该知道编译器是通过使用以下选项对“树”执行一组转换来实现的: