建立延續的功能
如果在分隔 reset
塊之外呼叫 shift
,它可以用於建立自己在 reset
塊內建立延續的函式。值得注意的是,shift
的型別不僅僅是 (((A => B) => C) => A)
,它實際上是 (((A => B) => C) => (A @cpsParam[B, C]))
。該註釋標記了需要 CPS 轉換的位置。在沒有 reset
的情況下呼叫 shift
的函式的返回型別會被該註釋感染。
在 reset
區塊內,A @cpsParam[B, C]
的值似乎具有 A
的值,但實際上它只是假裝。完成計算所需的延續型別為 A => B
,因此返回此型別的方法後面的程式碼必須返回 B
。C
是真實返回型別,在 CPS 轉換後,函式呼叫的型別為 C
。
現在,這個例子取自庫的 Scaladoc
val sessions = new HashMap[UUID, Int=>Unit]
def ask(prompt: String): Int @suspendable = // alias for @cpsParam[Unit, Unit]. @cps[Unit] is also an alias. (@cps[A] = @cpsParam[A,A])
shift {
k: (Int => Unit) => {
println(prompt)
val id = uuidGen
sessions += id -> k
}
}
def go(): Unit = reset {
println("Welcome!")
val first = ask("Please give me a number") // Uses CPS just like shift
val second = ask("Please enter another number")
printf("The sum of your numbers is: %d\n", first + second)
}
這裡,ask
會將延續儲存到地圖中,稍後其他一些程式碼可以檢索該會話並將查詢結果傳遞給使用者。通過這種方式,go
實際上可以使用非同步庫,而其程式碼看起來像普通的命令式程式碼。