问题标签 [continuation-passing]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++14 - 具有 unique_ptr 和矩阵的持久表达式模板
我想使用表达式模板来创建一个跨语句持续存在的对象树。构建树最初涉及使用 Eigen 线性代数库进行一些计算。持久表达式模板将具有其他方法来通过以不同方式遍历树来计算其他数量(但我还没有)。
为了避免临时对象超出范围的问题,子表达式对象通过std::unique_ptr
. 随着表达式树的构建,指针应该向上传播,这样持有根对象的指针就可以确保所有对象都保持活动状态。由于 Eigen 创建的表达式模板包含对在语句末尾超出范围的临时对象的引用,因此情况变得复杂,因此必须在构建树时评估所有 Eigen 表达式。
val
下面是一个按比例缩小的实现,当类型是一个持有整数的对象时,它似乎可以工作,但是对于 Matrix 类型,它在构造output_xpr
对象时会崩溃。崩溃的原因似乎是 Eigen 的矩阵乘积表达式模板 ( Eigen::GeneralProduct
) 在使用之前就已损坏。但是,在崩溃发生之前,我自己的表达式对象或 of 的析构函数GeneralProduct
似乎都没有被调用,并且 valgrind 没有检测到任何无效的内存访问。
任何帮助都感激不尽!我也很欣赏关于我将移动构造函数与静态继承一起使用的评论,也许问题出在某个地方。
scala - 这个尾递归斐波那契函数的定义是尾递归的吗?
我已经看到了以下 F# 对连续传递式斐波那契函数的定义,我一直认为它是尾递归的:
在 Scala 中尝试等效代码时,我使用了现有的 @tailrec,当 Scala 编译器通知我递归调用不在尾部位置时,我措手不及:
我相信我的 Scala 实现等同于 F#,所以我想知道为什么该函数不是尾递归的?
erlang - Erlang 实现了一个 amb 操作符。
在维基百科上,它说使用 call/cc 您可以实现 amb 运算符以进行非确定性选择,我的问题是您将如何以一种语言实现 amb 运算符,在这种语言中,对延续的唯一支持是以延续传递样式编写,例如二郎?
javascript - 为什么这个功能 CPS 功能在 Chrome 中有效,而在其他浏览器中无效?
我试图执行这个关于 CPS 的简单代码。这适用于 Chrome 43,但不适用于 Firefox 和 Opera……怎么了?(所以 Linux Mint 17 )
c++ - 如果方法的调用者不需要数据所有权,有什么好方法可以避免复制?
这是我最近在思考的问题。假设我们的接口是一个成员函数,它返回复制成本高且移动成本低的对象(std::string、std::vector 等)。一些实现可能会计算结果并返回一个临时对象,而其他实现可能只是返回一个成员对象。
示例代码来说明:
还有各种“客户”。有些只读取数据,有些需要所有权。
上面的代码编写得很好,但没有达到应有的效率。以下是所有组合:
解决这种情况的好方法是什么?
我想出了两种方法,但我确信有更好的解决方案。
在我的第一次尝试中,我编写了一个包含 T 值或指向 const T 的指针的 DelayedCopy 包装器。它非常丑陋,需要额外的努力,引入了多余的移动,妨碍了复制省略,并且可能还有许多其他问题。
我的第二个想法是continuation-passing style,它工作得很好,但将成员函数转换为成员函数模板。我知道,有 std::function,但它有它的开销,所以在性能方面它可能是不可接受的。
示例代码:
输出:
是否有更好的技术来传递避免额外副本但仍然通用的值(允许返回临时成员和数据成员)?
附带说明:代码是用 C++11 中的 g++ 5.2 和 clang 3.7 编译的。在 C++14 和 C++1z 中,DelayedCopy 无法编译,我不确定这是否是我的错。
haskell - 如何在 State monad 中包装链式有状态计算?
我有这种格式的计算:s -> a -> s
,s
某些状态的类型在哪里。这样一个函数的结果也是下一次求值的状态。例如,
然后,appendInt "Int: " 1
将给予"Int: 1"
,同时(appendInt $ appendInt "Int: 1") 2
将给予"Int: 12"
。但是,我找不到将这种计算放入State
Monad 的方法。
第一个猜测是s -> (s,s)
,但随后a
无法传入。然后,我尝试了 ,但(a -> s) -> (s, a -> s)
又一次无法获得。不起作用,因为是输入而不是输出。s
a
s -> (a,s)
a
那么我应该如何包装这个计算呢?State
单子适合这个吗?
javascript - 在 CPS 计算期间使用 bind 清除调用堆栈
编辑:我的这个问题已经证明是非常不合适的。我仍然相信,尤其是通过评论,它可能会提供一些思考的食物,但如果能达到足够多的票数来关闭它,我会理解的。
在研究一篇关于通过在 JavaScript 中模拟 call/cc 来展开调用堆栈的方法的非常有趣的论文的研究期间(延续和回调之间有什么区别?)我遇到了似乎是对主要使用方式的根本改进使 JS 函数调用异步。
最流行的方式是setTimeout(fun, 0)
。这种构造fun
从当前执行线程中调用,并允许事件队列中的其他作业进行。然而,当轮到它时,fun
它在所有情况下都维护它的整个调用堆栈。
但是,如果像上面提到的论文那样,将代码更改为setTimeout.bind(null, fun, 0)
并且我们正在以连续传递样式进行编程(没有return
要记住的指令),那么调用堆栈将fun
被清除并返回深度 1。
可以在一个示例中看到所有这些在起作用。在 Chrome、FF、IE、Opera 中验证。
示例 HTML 页面非常易于下载并在打开开发者工具的浏览器中运行。第 18 行和第 42 行有两条暂停指令,您可以在其中观察由setTimeout
.
问题是:为什么它的行为与普通的调用setTimeout.bind()
完全不同?setTimeout
有人可以说明发生了什么吗?
haskell - Haskell Continuations 在野外控制反转?
续篇很有趣。特别有趣的是它们如何包含所有其他单子。另外,我听说它们被大量用于优化。我听说它们可以用来做的一件事是对事物的控制反转。比如gui之类的。我想知道 Haskell 中是否有一个使用它的库示例。
我对它是否受欢迎或其他任何事情都不是特别感兴趣。我主要是为了阅读。需要考虑的因素:
- 直接延续,而不是延续导数:它应该基于类似于
newtype Cont r a = Cont ((a -> r) -> r)
. (组合器是可以的,但应该可以理解直接延续是如何适应它的。) - 用于控制反转:延续用于许多用途,但我主要对 GUI 类型的东西或控制反转使事情更容易的其他地方感兴趣
- 普遍性:延续应该是普遍的控制结构。
- 写得好:代码应该更容易阅读和学习。
(我想这样做的原因是我发现仅基于函数的 Continuations 是一个非常纯粹的函数式编程概念,同时非常强大。有一个我喜欢的库,它是非常直接的函数式编程,我很想继续扩展它。)
注意:作为直接的延续并不是很重要。控制反转是我主要追求的。
f# - F#中的尾递归:堆栈溢出
作为作业的一部分,我正在尝试在大图上实现 Kosaraju 的算法 [MOOC Algo I Stanford on Coursera]
https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm
当前代码在一个小图上工作,但我在运行时执行期间遇到了 Stack Overflow。
尽管已阅读 F# 专家中的相关章节,或网站和 SO 上的其他可用示例,但我仍然不知道如何使用 continuation 来解决这个问题
下面是通用的完整代码,但是在执行 DFSLoop1 和里面的递归函数 DFSsub 时它已经失败了。我认为我没有使函数尾递归[因为说明
?]
但我不明白如何正确实施延续。
当只考虑失败的部分时,DFSLoop1 将我们将应用深度优先搜索的图作为参数。我们需要将完成时间记录为算法的一部分,以便在第二个 DFS 循环 (DFSLoop2) 中继续进行算法的第二部分 [当然在此之前我们失败了]。
这是一个带有简单图形示例的文本文件
(导致溢出的一个是 70Mo 大,大约有 900,000 个节点)
编辑
首先澄清一些事情这是“伪代码”
输入:以邻接表表示的有向图 G = (V,E)。假设顶点 V 标记为 1、2、3、...。. . , n. 1. 让 Grev 表示所有弧的方向都被反转后的图 G。2. 在Grev 上运行DFS-Loop 子程序,按照给定的顺序处理顶点,得到每个顶点v ∈ V 的完成时间f(v)。3. 在 G 上运行 DFS-Loop 子程序,按照 f(v) 的降序处理顶点,为每个顶点 v ∈ V 分配一个领导者。4. G 的强连通分量对应于 G 的顶点,它们共享一个共同的领导者。 图 2:我们的 SCC 算法的顶层。f 值和领导者分别在对 DFS-Loop 的第一次和第二次调用中计算(见下文)。
输入:以邻接表表示的有向图 G = (V,E)。1. 将全局变量 t 初始化为 0。[这会跟踪已完全探索的顶点数。] 2. 将全局变量 s 初始化为 NULL。[这会跟踪调用最后一次 DFS 调用的顶点。] 3. 对于 i = n 到 1: [在第一次调用中,顶点标记为 1、2、...。. . , n 任意。在第二次调用中,顶点由第一次调用的 f(v) 值标记。] (a) 如果 i 尚未探索:i。设置 s := i ii。DFS(G, i) 图 3:DFS-Loop 子程序。
输入:有向图 G = (V,E),采用邻接表表示,源顶点 i ∈ V。1. 将 i 标记为已探索。[在整个 DFS-Loop 调用期间一直在探索。] 2. 设置 leader(i) := s 3. 对于每个弧 (i, j) ∈ G:(a) 如果 j 尚未探索:i。DFS(G, j) 4. t + + 5. 设置 f(i) := t 图 4:DFS 子程序。f 值只需要在第一次调用 DFS-Loop 时计算,而领导值只需要在第二次调用 DFS-Loop 时计算。
编辑 我已经修改了代码,在经验丰富的程序员(一个 lisper 但没有 F# 经验)的帮助下,稍微简化了第一部分,以便更快地获得一个示例,而无需担心与此讨论无关的代码。
代码只关注算法的一半,运行一次 DFS 以获得反向树的完成时间。
这是代码的第一部分,只是为了创建一个小示例 y 是原始树。元组的第一个元素是父元素,第二个元素是子元素。但我们将使用反向树
所以基本上图表是 (1->2->3->1)::(4->5->6->7->8->....->99999->10000) 和反向图是 (1->3->2->1)::(10000->9999->....->4)
这是以直接样式编写的主要代码
它不是尾递归的,所以我们使用延续,这里是适应 CPS 风格的相同代码:
两个代码都编译并为小示例(注释中的那个)或我们正在使用的同一棵树提供相同的结果,但大小更小(1000而不是100000)
所以我不认为这是算法中的错误,我们有相同的树结构,只是更大的树导致了问题。在我们看来,续篇写得很好。我们已经明确输入了代码。并且所有呼叫在所有情况下都以继续结束...
我们正在寻求专家建议!!!谢谢 !!!
scheme - 为有中断的语言编写解释器
我正在尝试在 Scheme 中为一种简单的编程语言编写解释器。现在,我正在编写一个程序来处理带有 break 语句的 while 循环。为了解决这个问题,我使用了 call/cc。
解析语言时,它看起来像这样:
变成
我解释这些陈述的方法如下:
其中 (M_State 语句 state) 返回当前状态更新以反映语句(例如状态 ((x) (2)) 表示 x = 2。 (M_State '(var x 5) '((x) (2))) 将返回((x)(5))。)
当我将它通过调试器时,行 ((null?body_line) (second-break-cont state)) 总是调用 second-break-cont,即使 body_line 不为空。我花了很多时间调试这个,但似乎找不到错误。任何帮助发现我的错误将不胜感激。