Lua中的呼叫/抄送-可能吗?

Lua中的呼叫/抄送-可能吗?,lua,continuations,callcc,Lua,Continuations,Callcc,维基百科上的文章说: “在任何支持闭包的语言中,都可以编写延续传递样式的程序,并手动实现call/cc” 要么这是真的,我需要知道如何去做,要么这不是真的,那句话需要更正。 如果这是真的,请告诉我如何在Lua中实现call/cc,因为我看不出如何实现。 我想如果Lua具有所解释的coroutine.clone函数,我将能够手动实现call/cc。 如果闭包不足以实现call/cc,那么还需要什么 以下文本为可选阅读。 注:Lua的协同程序表有一个一次性的延续。一个coroutine.clone函

维基百科上的文章说:
“在任何支持闭包的语言中,都可以编写延续传递样式的程序,并手动实现call/cc

要么这是真的,我需要知道如何去做,要么这不是真的,那句话需要更正。

如果这是真的,请告诉我如何在Lua中实现call/cc,因为我看不出如何实现。

我想如果Lua具有所解释的coroutine.clone函数,我将能够手动实现call/cc。

如果闭包不足以实现call/cc,那么还需要什么

以下文本为可选阅读。
注:Lua的协同程序表有一个一次性的延续。一个coroutine.clone函数将允许我克隆它以多次调用它,从而有效地使call/cc成为可能(除非我误解了call/cc)。但是,Lua中不存在克隆功能。Lua IRC频道上有人建议我使用Pluto库(它实现了序列化)封送一个协同路由,复制它,然后解组并再次使用它。虽然这可能会起作用,但我更感兴趣的是call/cc的理论实现,以及找到一种语言需要具备的实际最低功能集,以便手动实现

编辑1:好的,大家,帮我一把,这花了我很长时间,因为我不知道任何方案,但我想出了一些应该能帮我们的办法。请看下面的代码。第一个是Scheme中的程序,第二个是Lua中的同一程序<希望这能帮助我们解决问题。我相信我们非常接近。

附言:这些例子摘自上节的第一个例子。 方案版本



Lua版本




我使用的是DrScheme和Lua for Windows,这两个工具都很容易下载和安装,很好用。

我想你忘了在接下来的过程中编写程序了 风格一旦这样做了,call/cc就变得微不足道了(在Lua或任何其他语言中), 因为continuation将是所有函数的显式参数(call/cc 包括在内)

PS:除了闭包,您还需要适当的尾部调用来继续编写程序
传递样式。

根据维基百科的引用,手动实现call/cc有两个先决条件:

  • 该语言必须支持闭包
  • 您必须以连续传递样式(CPS)编写程序
  • 我想你不会喜欢的

    要以连续传递样式编写程序,请执行以下操作:

  • 每个函数都必须接受一个连续参数
  • 函数必须通过调用其continuation返回
  • 因此,使用
    k
    作为continuation参数的名称,函数如下所示:

    function multiplyadd(k, x, y, z) return k(x * y + z) end
    
    multiplyadd(print, 2, 4, 1)
    
    顶层可能使用
    print
    作为其延续,因此在顶层调用
    multiplyadd
    如下所示:

    function multiplyadd(k, x, y, z) return k(x * y + z) end
    
    multiplyadd(print, 2, 4, 1)
    
    有了这个脚手架,我们可以将call/cc定义为

    function callcc(k,f) return f(k,k) end
    
    请注意,由于
    *
    +
    不在CPS中,因此上述
    多重添加实际上是欺骗。在CPS表单中添加所有运算符,用CPS等价物替换所有Lua库函数,并将所有代码翻译/生成为CPS,这是非常繁琐的;请参阅。

    关键短语是

    可以以连续传递方式实现程序

    (我的重点)你可以通过使用常规的“直接样式”程序,并通过一种称为CPS转换的程序转换将它们转换为连续传递样式(CPS)来实现这一点。关键是
    call/cc
    的CPS转换是一个简单的函数

    这对程序员不实用。CPS转换有两个用途:

    • 作为研究语言特征,特别是控制算子的理论思想
    • 作为使用CPS作为中间语言的编译器中的过程

    您不想在Lua代码上进行CPS转换,尤其是不想手动进行。

    回答有关Lua中call/cc计划的问题:Lua中没有call/cc计划。捕获延续要么代价太高,要么需要一些代码分析,远远超出了Lua编译器的能力。还有一个问题,Lua连续体可能包含C中的部分


    然而,使用协同路由,我们已经可以在Lua中实现call/cc1(一次性延续)。这对于continuations的许多用途来说已经足够了。

    这是我的cps转换方案,只需将要转换的每个函数传递给它即可

    (定义(cps转换函数.函数)
    #因为“帮助”在两个不同的地方被调用。。。
    (定义(帮助)(错误“语法:(cps转换f1 f2…))
    #单功能转换器
    (定义(转换函数)
    #“name”包含以“cps-”为前缀的函数名
    (让([名称(字符串->符号
    (字符串附加“cps-”(符号->字符串函数)))]
    #在全球环境中定义“cps-*”的肮脏黑客
    `(eval)(开始
    #防止对功能进行评估所必需的
    (定义、名称#f)
    #魔力
    (set!、名称(lambda(k.args)(k(func args '))))
    #全球环境
    (交互环境)
    #先决条件…如果条件不满足,请致电帮助
    (如果(符号?功能)
    #功能是一种符号
    (续)
    #如果只有一个函数要转换
    [(空?函数)(转换函数)]
    #否则,确保每个其他“功能”都是符号,并相互转换
    [(每个符号?功能)(应用转换功能)]
    #哎呀!不符合条件!
    [其他(帮助)])
    #前一个“if”中的Else子句
    (帮助)
    
    有可能: Lua编译器的类型脚本+ 在JS中调用cc