我不确定我是否理解分隔的延续运算符对prompt/control
和reset/shift
. 我了解一些基本的使用示例,但在这些示例中,它们的行为是相同的。
我在Dariusz Biernacki 和 Olivier Danvy的“关于分隔连续的动态范围”中找到了这个例子:
reset
(fn () => shift (fn k => 10 + (k 100))
+ shift (fn k’ => 1))
prompt
(fn () => control (fn k => 10 + (k 100))
+ control (fn k’ => 1))
racket/control
我已将其翻译成 Scheme 并使用库在 Racket 中以预期结果成功运行:
(reset (+ (shift k (+ 10 (k 100)))
(shift kk 1)))
;; ==> 11
(prompt (+ (control k (+ 10 (k 100)))
(control kk 1)))
;; ==> 1
他们的解释是,
在第一种情况下,当
k
被应用时,表达式在可以在功能上表示为的上下文中以及在可以表示为的元上下文中shift (fn kk => 1)
进行评估;此上下文被捕获并丢弃,中间答案是;这个中间答案从元上下文插入到顶层上下文中,即 应用于; 下一个中间答案是 ;这是最终的答案,因为元上下文是空的。fn v => 100 + v
(fn v => 10 + v) :: nil
1
fn v => 10 + v
1
11
在第二种情况下,当
k
被应用时,表达式控件 在由组合和(因此可以在功能上表示为)产生的上下文中以及在为空的元上下文中(fn kk => 1)
进行评估 ;此上下文被捕获并丢弃,中间答案是;这是最终的答案,因为元上下文是空的。fn v => 10 + v
fn v => 100 + v
fn v => 10 + (100 + v)
1
我对“元上下文”的想法感到困惑,他们将其定义为
直观地说,评估上下文表示直到
最近的封闭分隔符的其余计算,而元上下文表示所有剩余的计算。
我在这里没有得到“所有剩余计算”的想法,我不确定为什么会出现(fn v => 10 + v) :: nil
在第一个示例中(为什么是那段代码?)
我想知道是否还有更多的例子,可能有更多的细节,说明这两对操作符之间的差异,可能没有太多使用形式语义,这真的让我头疼。
编辑:我还看到两个shift
被包围的表达式的顺序确实有所不同:如果我交换它们,那么结果1
对于两者都是control
and reset
。