我正在研究Oleg和Asai划定的“傻瓜”续篇(http://pllab.is.ocha.ac.jp/~asai/cw2011tutorial/main-e.pdf)但本文使用的是shift /重置形式主义,而不是奥列格的delimcc中提供的提示。所以我有几个问题:
首先,什么是提示?为什么在shift
和其他函数中传递?知道什么是subcont也不错,但我愿意跳过这个,因为我只是想通过论文。此外,shift
和shift0
之间的区别是什么?它们与论文中的shift
如何对应。
此外,delimcc中的reset
是什么?我的直觉告诉我,new_prompt
和push_prompt
某种程度上与reset
相对应。但我在这里也需要澄清一些。
编辑:我能够从论文中翻译一个简单的例子,我的直觉证明是正确的。但是我想要对这些差异进行真正的解释,为什么delimcc就是这样的。这是两个版本,如果有人感兴趣
纸张:
reset (fun () -> 3 + shift (fun _ -> 5 * 2) - 1)
Delimcc:
let _ = let open Delimcc in
let np = new_prompt () in
push_prompt np (fun () -> 3 + (shift np (fun _ -> 5 * 2)) - 1)
答案 0 :(得分:10)
我建议您阅读this paper的开头,这是Oleg的delimcc
演示文稿的期刊版本。这样可以让您对delimcc
有一个合理的理解,让您将文章的移位/重置示例移植到delimcc
的多提示设置。
您可能感兴趣的两个引号。第一个是我上面提到的期刊版本:
已经熟悉分界控件的读者可能将delimcc视为普通的概括 移位/重置以控制任意多种“风味”的分隔符。函数
new_prompt
创建一个新的唯一控件分隔符或提示符 味道。表达式push_prompt p (fun () -> e)
,概括reset e
,将控制分隔符p
放在堆栈上,然后评估e
;take_subcont p f
删除堆栈的前缀到最近的堆栈 标有给定p
的框架。堆栈的移除部分,与 终止分隔符p
被截断,被打包为一个延续对象 抽象类型子包并传递给take_subcont
的参数f
。函数push_subcont
可能会将已删除的堆栈帧放回堆栈中 在不同的上下文中,从而恢复捕获的分隔延续。
第二个来自GNU Guile's documentation
还在吗?因此,当实现像
call-with-prompt
这样的分隔控制运算符时,需要做出两个决策。首先,处理程序是在提示符之内还是之外运行?让处理程序在提示符下运行允许处理程序内的中止返回到相同的提示处理程序,这通常很有用。但是它会阻止来自处理程序的尾调用,所以它不那么通用。同样,调用捕获的延续会恢复提示吗?我们再次对方便与正确的尾调用进行权衡。
这些决定在Felleisen F 运算符中捕获。如果continuation和处理程序都没有隐式添加提示,则运算符称为 -F - 。 Guile的
call-with-prompt
和abort-to-prompt
就是这种情况。如果continuation和handler都隐式添加提示,则运算符为 + F + 。
shift
和reset
就是这样的运营商。
总结:你是正确的,调用new_prompt
来获取提示,然后push_prompt
安装它是获取reset
的方法。实际上,您只需要调用new_prompt
一次,并且可以始终推送到同一个全局提示符,并获得通常的shift
/ reset
行为(声明不同的提示只会为您提供更多信息)自由)。
最后,shift
可以使用delimcc
的原语进行定义,这就是在库中完成的操作。 shift
调用take_subcont
,立即重新安装(相同)提示,并向用户提供将重启中止计算的函数。 shift0
执行相同的操作,但不会重新安装提示。在delimcc
代码中:
let shift p f = take_subcont p (fun sk () ->
push_prompt p (fun () -> (f (fun c ->
push_delim_subcont sk (fun () -> c)))))
let shift0 p f = take_subcont p (fun sk () ->
f (fun c -> push_delim_subcont sk (fun () -> c)))