为什么不';我不能在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运行代码的方式完全相同。