维基百科文章
Continuation表示:
“在支持闭包的任何语言中,可以编写继续传递风格的程序,并手动实现call / cc。
要么这是真的,我需要知道如何做,否则是不正确的,那个说法需要纠正。
如果这是真的,请告诉我如何在Lua中实现call / cc,因为我看不到如何。
如果Lua具有如同 here所述的coroutine.clone函数,我可以手动实现call / cc。
如果闭包不足以实现call / cc,那么还需要什么?
“在支持闭包的任何语言中,可以编写继续传递风格的程序,并手动实现call / cc。
要么这是真的,我需要知道如何做,否则是不正确的,那个说法需要纠正。
如果这是真的,请告诉我如何在Lua中实现call / cc,因为我看不到如何。
如果Lua具有如同 here所述的coroutine.clone函数,我可以手动实现call / cc。
如果闭包不足以实现call / cc,那么还需要什么?
下面的文本是可选阅读。
路易斯安那州有一个连续的协同工作台。一个coroutine.clone函数将允许我克隆它多次调用它,从而有效地使呼叫/ cc成为可能(除非我误会呼叫/ cc)。但是,在Lua中不存在克隆功能。 Lua IRC频道上的人建议我使用Pluto库(它实现序列化)来组织协同程序,复制它,然后将其解组并重新使用。虽然这可能会起作用,但我对于call / cc的理论实现和对语言需要具备的实际最小功能集进行手动实现更感兴趣。
编辑1:好的人,帮我在这里,这花了我很长时间,因为我不知道任何计划,但我想出了应该帮助我们的东西。请看下面的代码。第一个是Scheme中的一个程序,第二个是程序,但是在Lua中。希望这将有助于我们。我相信我们非常接近
这些例子摘自the Wikipedia article on CallCC的第一个例子。
计划版本
(define call/cc call-with-current-continuation) ; callcc CPS-transformed (thanks to the people from the #scheme channel at freenode.net) (define cpscallcc (lambda (consumer k) (let ((cc (lambda (result) (k result)))) (consumer cc k)))) ; this is the continuation we will use to display the "returned" values (define main-continuation (lambda (result) (display "--> ") (display result) (newline))) ; define f function non-CPS (define (f return) (return 2) 3) ; these are my past attempts at defining a CPS f function ;(define (cps-f return k) ; (k (return 2)) 3) ;(define (cps-f return k) ; (k (lambda () ; (return 2) ; 3))) ; this is what I came up with - I'm not sure if this is correctly CPS-transformed but I believe so (define (cps-f return k) (return 2) (k 3)) ; call the non-CPS f function (display (f (lambda (x) x))) ; displays 3 (newline) ; call the non-CPS f function with call/cc (I don't understand what this does) (display (call/cc f)) ; displays 2 (newline) ; now call the CPS version of the f function (cps-f (lambda (x) x) main-continuation) ; displays --> 3 ; now call the CPS version of the f function with the CPS version of call/cc (cpscallcc cps-f main-continuation) ; displays --> 2 but then it also displays --> 3 afterwards -> I'm not sure why it displays the 3 afterwards,as it should only display the 2 just like the non-CPS versions above
Lua版本
-- callcc CPS-version cpscallcc = function(consumer,k) local cc = function(result) return k(result) -- ?or k(result) end return consumer(cc,k) -- ?or return consumer(cc,k) end -- define f function non-CPS f = function(ret) ret(2) return 3 end -- define f function CPS-version (again,not sure this is correct) cps_f = function(ret,k) ret(2) k(3) end -- call the non-CPS f function print(f(function(x) return x end)) -- we cant call the non-CPS f function with callcc because -- Lua doesnt have callcc,but the line below displays the correct expected output (maybe by accident) --cpscallcc(f,print) -- now call the CPS version of the f function cps_f( function(x) return x end,print ) -- displays 3 ; now call the CPS version of the f function with the CPS version of call/cc cpscallcc( cps_f,print) -- displays 2 and then 3 just like the Scheme version!! -- so apparently the translation from Scheme to Lua is correct...
我正在使用DrScheme和Lua for Windows – 对于任何想要帮助的人来说,这两个都是很容易下载和安装刚刚起作用的工具。
解决方法
维基百科报价有两个手动实现call / cc的先决条件:
>语言必须支持闭包
>您必须以继续传递风格(CPS)编写程序
我怀疑你不会喜欢#2。
写你的程序继续传递风格:
function multiplyadd(k,x,y,z) return k(x * y + z) end
toplevel可能会使用print作为其延续,因此在顶层调用multiplyadd将如下所示:
multiplyadd(print,2,4,1)
使用脚手架,我们可以定义call / cc
function callcc(k,f) return f(k,k) end
请注意,上述multiplyadd实际上是*,而不是CPS中的秘籍。以CPS格式添加所有运算符是非常繁琐的,用CPS代替所有Lua库函数,并将所有代码转换/生成CPS;见details here。