在尾递归函数中使用管道时出现堆栈溢出异常

2024-02-26

我有一个简单的游戏循环实现

let gameLoop gamestate =     
    let rec innerLoop prev gamestate =
        let now = getTicks()
        let delta = now - prev
        gamestate 
        |> readInput delta
        |> update delta
        |> render delta
        |> innerLoop delta             

    innerLoop 0L gamestate 

此实现会引发 stackoverflow 异常。在我看来这应该是尾递归。我可以这样解决

let gameLoop gamestate =     
    let rec innerLoop prev gamestate =
        let now = getTicks()
        let delta = now - prev
        let newState = gamestate 
            |> readInput delta
            |> update delta
            |> render delta

        innerLoop now newState

    innerLoop 0L gamestate  

所以我的问题是为什么第一个代码示例会抛出 stackoverflow 异常。


我认为答案与线程中的相同Vandroiy https://stackoverflow.com/users/4191347/vandroiy链接:当你有

a
|> f b

然后在调试模式下,编译器可能会像字面解释一样编译它

(f b) a

并明确计算f b一步一步将其应用到a在第二步中。带参数的调用a仍然是尾调用,但如果编译器不发出tail.操作码前缀(因为尾部调用被关闭,因为它们默认处于调试模式),那么您将通过显式调用增加堆栈并最终导致堆栈溢出。

另一方面,如果你写

f b a

直接那么这不会发生:编译器不会部分应用f,并且会认识到这是一个直接递归调用并将其优化为循环(即使在调试模式下)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在尾递归函数中使用管道时出现堆栈溢出异常 的相关文章

随机推荐

  • MySQL插入语句队列

    我们正在构建一个 ajax 应用程序 其中用户输入被提交到 php 脚本进行处理 我们目前正在将每个请求写入日志文件以进行跟踪 我想将此跟踪移至数据库表中 但我不想在请求后运行插入语句 我想做的是建立一个需要在 MySQL 数据库上处理的事
  • 将 SweetAlert2 与 TypeScript 结合使用,找不到模块“sweetalert2/dist/sweetalert2.js”的声明文件

    我正在将我的一个项目迁移到 TypeScript 在该项目中甜蜜警报2 https sweetalert2 github io 使用库 导入 SweetAlert2 JS 和 CSS 的默认方式是 import Swal from swee
  • 数据库表和面向对象的类之间有关系吗?

    每次我编程时 我都会认识到类和表之间的这种关系 或者是我的想象 您可以为每个数据库表一个类或每个类一个表 即 tables customer products order classes customer products order ma
  • 如何将自定义参数传递给 Locust 测试类?

    我目前正在使用环境变量将自定义参数传递给我的负载测试 例如 我的测试类如下所示 from locust import HttpLocust TaskSet task import os class UserBehavior TaskSet
  • SwiftUI iOS14 GeometryReader 无效的框架尺寸

    我的 GeometryReader 在 iOS13 中工作正常 但现在在 iOS14 中出现线程问题 框架尺寸无效 负或非有限 我打印了读者应该返回的尺寸 看起来不错 该应用程序仍然基本上可以工作 但看起来有点奇怪 因为引入了一些填充 有谁
  • Node.js:如何为 prod 和 staging 设置不同的变量

    我正在使用 Express 并且需要为每个服务器 登台和生产 使用不同的凭据 我可以在 server coffee 文件中设置变量 但随后我需要访问不同文件中的这些变量 server coffee app configure product
  • 我可以在 EJS 中渲染多个源吗

    我尝试使用来自 2 个不同源的数据 但使用 EJS JS 和 Node 将它们呈现在同一个 HTML 页面上 这就是我正在尝试的 app set view engine ejs app get function req res res re
  • 无法建立新连接

    import requests url http ES search demo com document record search pretty true data query bool must text record document
  • 谷歌地图缩放看起来很奇怪

    我遇到了 Google 地图问题 除了缩放按钮似乎混乱之外 一切似乎都正常 Here is an image of the map 我猜有些东西是重叠的 但我不太确定 看来我来晚了 还是想分享一下我的想法 编辑库的核心 CSS 并不是一个好
  • 如何使用 GLFW 轮询 libdispatch 块中的事件?

    跟进答案如何将 GLUT 与 libdispatch 一起使用 https stackoverflow com q 12553563 64860 我现在改用 GLFW 以下代码设置一个窗口 设置一个计时器来轮询事件 并随着时间的推移将渲染更
  • 将值添加到空 Swift 数组

    我不知道如何在 Swift 中向空数组添加值 我尝试以两种不同的方式从空数组开始 var emptyArray Int emptyArray Int and var emptyArray 顺便问一下 这两种创建空数组的方式有什么区别 我尝试
  • 如何使用appledoc生成类似Apple的文档

    我正在阅读如何生成类似 Apple 的 HTML 文档的文章 here http gentlebytes com appledoc docs examples basic 我的问题是命令行的用途 我们如何将命令行和 appledoc xco
  • Outlook JS Addin - 撰写表单 - 如何检查事件/消息是否已保存?

    Outlook 加载项 office js 的撰写表单中是否有一种方法可以检查表单后面的对象 在我的例子中是日历事件 是否已保存 检查物品ID 如果未定义 则消息未存储 如果存在 则消息来自草稿 请参阅Office context mail
  • Process.GetProcesses 返回所有登录用户的进程?

    在允许多个用户同时登录一台机器的windows环境中 当我们调用Process GetProcesses 它是否返回进行此调用的登录用户的进程 还是返回所有登录用户的进程 我查看了 MSDN 页面 但找不到此信息 该函数返回本地计算机上运行
  • socket.error[Errno 99] 无法分配请求的地址

    昨天 我创建了一个名为的 python 脚本sniffer ip header decode py 但我遇到了以下错误 Traceback most recent call last File sniffer ip header decod
  • 通过 (...) 时避免参数重复

    考虑功能 f lt function x X mean c x X 我怎样才能自动 通过操纵f 更改签名f 这样它就可以与lapply 即不返回以下明显的错误 lapply X list 1 FUN f X 1 Error in lappl
  • XMLHttpRequest:浏览器支持 sendAsBinary?

    Firefox 是唯一支持 sendAsBinary 方法的吗 目前 我相信只有 FF3 支持此功能 尽管有一个解决方法 http code google com p chromium issues detail id 35705 for
  • Web 材质组件与 Angular Material 2 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 最近 MDL Material Design Lite 项目的后继项目推出Web 的材料组件 http
  • 如何在 React Native 中打开现有项目?

    我第一次使用 React Native 时 在我的 MacBook 上成功安装了用于 iOS 开发的所有内容 并且能够创建一个项目并在手机上查看它 然而 现在我回到它 我似乎无法弄清楚如何打开我现有的项目 我尝试过寻找指南 但我能找到的唯一
  • 在尾递归函数中使用管道时出现堆栈溢出异常

    我有一个简单的游戏循环实现 let gameLoop gamestate let rec innerLoop prev gamestate let now getTicks let delta now prev gamestate gt r