问题标签 [trampolines]

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.

0 投票
3 回答
2280 浏览

scala - Applicative vs. monadic 组合器和 Scalaz 中的自由 monad

几周前Dragisa Krsmanovic在这里问了一个问题,关于如何在 Scalaz 7 中使用 free monad 来避免这种情况下的堆栈溢出(我对他的代码做了一些修改):

我认为只需将蹦床举起来就StateT可以了:

但它仍然会破坏堆栈,所以我只是将其发布为评论。

Dave Stevens刚刚指出,使用 applicative*>而不是 monadic 的排序flatMap实际上工作得很好:

(嗯,它当然超级慢,因为这是你在 Scala 中做类似这样有趣的事情所付出的代价,但至少没有堆栈溢出。)

这里发生了什么?我认为这种差异可能没有原则上的原因,但我真的不知道实施中会发生什么,并且目前没有时间进行挖掘。但我很好奇,如果其他人知道会很酷。

0 投票
1 回答
390 浏览

scala - 蹦床作为函子

我正在尝试将 Trampoline[+A] 演示为仿函数(即提供 map[B](f: A = >B))。我将 Trampoline 的经典实现理解为Stackless Scala中描述的 Monad 。
但是,有没有办法只使用 Trampoline 的 Done 和 More 子类来实现地图功能(而不是flatMap),还是我还需要添加 Flatmap 子类?

0 投票
3 回答
13332 浏览

javascript - 如何理解 JavaScript 中的蹦床?

这是代码:

我读过蹦床是用来处理溢出问题的,所以函数不会只是不断地调用自己并导致堆栈填满。

但是这个片段是如何起作用的呢?特别是trampoline功能?它究竟做了什么,while又是如何实现目标的?

0 投票
2 回答
421 浏览

c++ - 使用模板将静态编码为实例方法蹦床功能

我正在尝试重新编码一些相当难看的模板编码。

作为参考,原文在这里:https ://codereview.stackexchange.com/questions/69545/recode-cc-trampoline-function-macros-using-templates

我的代码与 CPython(C 库)接口。Python 运行时看到 "myInst.foo" ,在表中查找 "foo" 并调用:

(请注意,可以将静态方法类型转换为 C 函数指针)

FooHandler 跳转到正确的 Final 实例的 Foo 方法。

实际上,句柄并不那么干净,并且有许多方法,每个方法都需要相同的处理程序(但具有不同的函数地址)。

我试图将处理程序机制抽象为一个基类,如下所示:

我目前陷入编译器错误(http://ideone.com/vOtbcD),所以我什至不确定该技术是否有效。

有什么方法可以做到这一点,或者这只是你真正需要宏的时候之一?

作为参考,原文在这里:https ://codereview.stackexchange.com/questions/69545/recode-cc-trampoline-function-macros-using-templates

可以看出,原始版本使用了相当丑陋的宏。

0 投票
2 回答
332 浏览

javascript - “蹦床”方法之间的区别

我最近开始学习 JS,这是我第一次涉足函数式语言领域。

在 npm 模块中做“蹦床”练习,functional-javascript-workshop发现我自己的解决方案和官方解决方案之间有一个有趣的区别。两者都工作得很好,但我不知道它们之间的实际区别到底是什么。我非常了解自己的解决方案,但不完全理解为什么另一个也有效。

我的解决方案

官方解决方案

具体来说,我对最后一部分很好奇——为什么官方解决方案会创建一个匿名函数而不是仅仅传递repeat

0 投票
3 回答
622 浏览

c++ - 使用 Lambda/Template/SFINAE 自动执行蹦床函数的 try/catch 保护

我有 100 个左右的蹦床功能。我想知道是否可以自动将每个包装在 try/catch 块中。

请提前警告,这不是一个简单的问题。我将首先用(简化的)代码描述问题,然后在下面尽我所能回答它,以便读者可以看到我在哪里。

Foo 有一个函数指针表:

编辑:这是一个C 函数指针表。所以它可以接受static W::w
签名在这里:http ://svn.python.org/projects/python/trunk/Include/object.h

编辑:我在这里尝试了一个测试用例:

如果一个特定的插槽被“加载”,这就是加载到其中的内容:

我正在尝试使用 lambdas 来完成此操作,以便绕过必须func53单独定义所有这些。像这样的东西:

但是,这无法捕获错误。我需要在 return 语句周围放置一个 try/catch:

但是,这会造成很多混乱。如果我能做到,那就太好了:

我的问题是:有没有办法编写这个trap函数(不使用#define)?


到目前为止,这是我想出的:

我认为这将传递所有必要的信息:

陷阱的定义可能如下所示:

这可能允许非常干净的语法:

在这一点上,我什至不确定是否违反了某些法律。 table->fp_53必须是有效的 C 函数指针。

传入非静态成员函数 ( &Base::f53>) 的地址不会违反这一点,因为它是一个模板参数,并且不会影响trap

同样,...应该没问题,因为 C 允许可变参数。

那么如果这确实是有效的,它可以被清理吗?

我的想法是:

1)也许 ... 应该作为一个包移回模板参数。
2)也许可以推导出trap的返回类型,并保存一个模板参数

3)那个Base::Func模板参数是非法的语法。我怀疑它甚至不接近合法的东西。这可能会破坏整个方法。

0 投票
2 回答
602 浏览

c++ - 异常安全蹦床的设计模式

这个问题从这里开始。然而,前一个问题的措辞如此糟糕(实际上是错误的),以至于有人建议我从头开始再问一次。

我有一个 C 函数指针表。

一些 C 代码(我们称之为 lib-X)有一个基本的构建块(我们称之为 X 对象)。每个 X 对象都可以调用该表上的函数。

这些表函数通常具有不同的签名(请参阅此处的 typedefs ),尽管多个函数可以共享相同的签名。表中大约有 100 个这样的函数。

在 C++ 中,每个 X 对象都有一个关联的 Final:Base 类。

我想将这些调用转发到 X 对象的相应 C++ Final 实例,但我想将它包含在 try/catch 中,因为 C++ 使用者可能会提供一个有问题的 Final。

所以我有一个 C++ 基类,它对表上的每个条目都有一个虚函数。

然后我有一个派生自基类的 C++ Final 类(可能很多;Final1 Final2 Final3 等)。

所以现在我只需要编写一个处理程序

  1. 获取第一个“self”参数(始终是指向调用函数的 X 对象的指针)

  2. 检索关联的 C++ 基类实例。

  3. 在 try catch 块中,调用相应的虚函数,将所有剩余参数转发到,

  4. ...这实际上将调用 Final 中的覆盖。

这有点像试图理解《盗梦空间》的情节。lib-X 实际上是 Python 运行时,尽管我试图保持一般性。

问题是这样的函数有几十个,这会导致一些非常混乱且无法维护的 C++ 代码——如果我必须为每个函数手动编写一个蹦床函数,看起来像:

(来源在这里

我试图想出一个紧凑的设计,允许这种异常安全的蹦床。

我目前的进度是[已删除,请参阅下面的答案]

0 投票
1 回答
310 浏览

monads - Trampolining scalaz' Monad.whileM_ 以防止堆栈溢出

我正在使用 scalaz'Monad.whileM_以功能方式实现 while 循环,如下所示:

虽然这适用于 small k,但它会导致大型 StackOverflow 错误k(例如 1000000)。有没有办法蹦床whileM_或者有更好的方法来保证堆栈安全?

0 投票
2 回答
433 浏览

closures - LLVM Trampoline 导致 SIGSEGV?

在阅读了使用蹦床在 LLVM 中生成闭包之后,我尝试编译一些在互联网上漂浮的蹦床示例(特别是这个)。gist 中给出的 LLVM IR 如下:

但是,使用clang trampolines.ll并执行它编译它会导致SIGSEGV(fish 给出的确切错误是fish: Job 1, './a.out ' terminated by signal SIGSEGV (Address boundary error))。

经过一些测试,事实证明“蹦床”函数的调用是导致 SIGSEGV 的指令,因为将其注释掉(并返回一个虚拟值)工作正常。

问题似乎也不在于clang两者,因为手动运行llvm-asllc也不起作用。在另一台机器上编译也不起作用。这让我相信我的机器或 LLVM 做错了什么。

我的铿锵版本:

0 投票
1 回答
253 浏览

scala - Scala:蹦床函数的扩展语法打破了尾递归

这是“Scala 中的函数式编程”第 13 章中的一个练习,用于实现一个用于解释尾递归函数的蹦床。

runTrampoline2不是尾递归的,并且会用我的测试输入溢出堆栈。此外,该tailrec注释给出了一个编译器错误runTrampoline2runTrampoline是尾递归的并通过注解的编译时检查。

我最好的选择是这两个蹦床之间的区别在于val捕获或不捕获单位的方式,如下所示:

否则这两个蹦床看起来和我一模一样。如果有人评论它们对这个问题很重要,我将包含 Free monad 和 Suspend、Return 和 FlatMap 构造函数的代码,但我认为它们不是。的尾递归是否被从 srunTrampoline2中泄漏出来的副作用破坏了val?谢谢!

一个月前我问了一个类似的问题,关于打破尾递归的类型注释: Scala: type annotations make tail recursion check fail


由艾文解决。这是蹦床的修正版本。每个递归调用都位于包含它的案例的最后。