如何解决如何使用 PureScript 进行调试?
问题
以下是一个最小的、人为的例子:
read :: FilePath -> Aff String
read f = do
log ("File: " <> f) -- (1)
readTextFile UTF8 f -- (2)
我想在 (1)
上的潜在错误发生之前在 (2)
中进行一些调试日志记录。到目前为止,在 Spago REPL 中执行以下代码适用于成功案例:
$ spago repl
> launchAff_ $ read "test/data/tree/root.txt"
File: test/data/tree/root.txt
unit
问题:如果 (2)
有错误 - file is directory here - ,(1)
似乎根本没有执行:
$ spago repl
> launchAff_ $ read "test/data/tree"
~/purescript-book/exercises/chapter9/.psci_modules/node_modules/Effect.Aff/foreign.js:532
throw util.fromLeft(step);
^
[Error: EISDIR: illegal operation on a directory,read] {
errno: -21,code: 'EISDIR',syscall: 'read'
}
原始问题更复杂,包括多层递归(请参阅 E-Book exercise 3),我需要在其中记录以调试上述错误。
问题
- 我如何正确记录这里即将发生的错误?
- (可选)是否有更复杂、完善的调试替代方案 - purescript-debugger?一个专门的 VS Code 调试扩展/功能将是锦上添花。
解决方法
首先,您观察到的症状并不意味着第一行没有执行。它确实总是执行,由于控制台在 PureScript REPL 中的工作方式,您只是看不到它的输出。输出被吞了。遗憾的是,这不是 REPL 的唯一问题。
您可以通过将 log
替换为 throwError
并观察错误总是被抛出来验证第一行总是被执行。或者,您可以让第一行修改可变单元格而不是写入控制台,然后检查单元格的内容。
最后,这只发生在 REPL 中。如果您将 launchAff_
调用放入 main
并运行该程序,您将始终获得控制台输出。
现在是手头的实际问题:如何调试跟踪。
如果您负担得起,登录到控制台是可以的,但还有一种更优雅的方式:Debug.Trace.trace
。
这个函数有一个隐藏的效果——即它的类型说它是纯的,但它在调用时确实产生了效果。这个小谎言让您可以在纯设置中使用 trace
,从而调试纯代码。不需要Effect
!只要只用于调试就可以,但不要放在生产代码中。
它的工作方式是它需要两个参数:第一个被打印到控制台,第二个是打印后要调用的函数,整个过程的结果是该函数返回的任何内容。例如:
calculateSomething :: Int -> Int -> Int
calculateSomething x y =
trace ("x = " <> show x) \_ ->
x + y
main :: Effect Unit
main =
log $ show $ calculateSomething 37 5
> npx spago run
'x = 37'
42
第一个参数可以是任何东西,而不仅仅是一个字符串。这让您可以轻松打印大量内容:
calculateSomething :: Int -> Int -> Int
calculateSomething x y =
trace { x,y } \_ ->
x + y
> npx spago run
{ x: 37,y: 5 }
42
或者,将其应用于您的代码:
read :: FilePath -> Aff String
read f = trace ("File: " <> f) \_ -> do
readTextFile UTF8 f
但这里有一个微妙的细节:只要您调用 read
,这种跟踪就会发生,即使结果 Aff
永远不会实际执行。如果您需要在有效执行时进行跟踪,则需要将 trace
调用作为操作的一部分,并注意不要使其成为序列中的第一个操作:
read :: FilePath -> Aff String
read f = do
pure unit
trace ("File: " <> f) \_ -> pure unit
readTextFile UTF8 f
当然,每次需要在有效上下文中进行跟踪时都这样做有点不方便,因此有一个特殊的函数可以为您执行此操作 - 它称为 traceM
:
read :: FilePath -> Aff String
read f = do
traceM ("File: " <> f)
readTextFile UTF8 f
如果您查看它的 source code,您会发现它与我在上面的示例中所做的完全一样。
可悲的是,当发生异常时,trace
不会在 REPL 中帮助您,因为它仍在打印到控制台,因此它仍然会因同样的原因被吞下。
但是即使没有被吞下,输出也有点乱,因为trace
实际上是彩色输出的(帮助你在其他输出中分辨出来),而PureScript REPL与颜色:
> calculateSomething 37 5
←[32m'x = 37'←[39m
42
,
除了 Fyodor Soikin's great answer 之外,我还发现了一个使用 VS Code 调试视图的变体。
1.) 确保build with sourcemaps:
spago build --purs-args "-g sourcemaps"
2.) 向 VS Code launch.json
添加调试配置:
{
"version": "0.2.0","configurations": [
{
"type": "pwa-node","request": "launch","name": "Launch Program","skipFiles": ["<node_internals>/**"],"runtimeArgs": ["-e","require('./output/Main/index.js').main()"],"smartStep": true // skips files without (valid) source map
}
]
}
将 "./output/Main/index.js"
/ .main()
替换为编译后的 .js
文件/要调试的函数。
3.) 设置断点并通过源映射支持逐步执行 .purs
文件。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。