为什么不';我不能在Elm REPL中的无限循环中从Debug.log获取输出吗?

为什么不';我不能在Elm REPL中的无限循环中从Debug.log获取输出吗?,elm,Elm,我正在用无限循环调试一些代码,但这很困难,因为我无法获得任何日志消息。下面是一个简化的例子: import Debug exposing (log) f x = let _ = log "Hello, world!" () in f x 如果我像f()那样在Elm REPL上运行它,它将无限循环,并且不会像我期望的那样打印出“你好,世界!” 我查看了Debug.log(接着是Native.Debug.log)的实现,但它似乎是在同步调用process.stdout.write

我正在用无限循环调试一些代码,但这很困难,因为我无法获得任何日志消息。下面是一个简化的例子:

import Debug exposing (log)

f x =
    let _ = log "Hello, world!" ()
    in f x
如果我像
f()
那样在Elm REPL上运行它,它将无限循环,并且不会像我期望的那样打印出
“你好,世界!”


我查看了
Debug.log
(接着是
Native.Debug.log
)的实现,但它似乎是在同步调用
process.stdout.write
console.log
,所以我很惊讶没有看到任何输出。

这只是Elm REPL中的一个bug

问题 我投身于Elm REPL的实现。相关功能如下:

这个
run
函数似乎就是执行一段代码的函数。看起来每一行代码都是通过Elm.Utils在子流程中执行的。打开包装。它的运行方式有两个问题:

  • 子流程的stdout未流化;它只在整个子流程完成后返回。所以,只要您等待代码完成求值,就什么也看不到
  • 如果您点击ctrl-c过早地结束计算(这很好,并返回Elm提示符),Elm Repl将忽略返回给它的标准输出。请注意:
Left(Utils.CommandFailed\u out err)->
投手失误

Utils.CommandFailed
结果包含stdout(它被绑定到
\u out
),但此代码忽略它,只是抛出错误

因此,基本上,Elm编译器或运行时并没有发生什么奇怪的事情,只是REPL在记录结果方面不如它可能的好

解决办法 作为一种解决方法,为了调试无限循环之类的东西,您可以

  • 将一些测试代码放入一个新文件,
    Scratch.elm
    ,比如
    x=f()
  • 使用
    elm make Scratch.elm--output Scratch.js编译代码
  • 使用
    节点scratch.js运行代码

  • 然后输出将流式传输到您的终端。

    我不知道Elm是否进行了优化,但如果是,则为忽略的绑定分配一个值可能会被优化掉。您是否尝试过在未将日志值分配给
    \uu
    的情况下执行此操作?在非无限递归情况下,它不会对其进行优化:
    fx=let=log“Hello,world!”(在5
    中),然后调用
    f()
    打印
    Hello,world
    @w.brian正确的编译器只有在能够证明未使用的表达式没有副作用的情况下才会优化它。优化
    let\uu=side\u影响foo
    中的表达式到
    foo
    将是一个非常不正确的优化。PS:
    let=…
    实际上并没有引入绑定。@sepp2k据编译器所知,log是一个纯函数,可以对其进行优化。它不纯净的事实对编译器来说是隐藏的,文档非常清楚地指出,出于这个原因,它不应该被用于生产;因为node.js是基于v8的,v8是在chrome web浏览器中执行javascript的。可以用Elm REPL伪造一些浏览器内容,也可以使用node.js进行计算,因此它与Elm REPL运行代码的方式完全相同。