debugging - 如何使用 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
问题:如果 -file (2)
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'
}
最初的问题更复杂,包括几层递归(参见电子书练习 3),我需要记录以调试上述错误。
问题
- 无论此处即将出现错误,我如何正确记录?
- (可选)是否有更复杂、更完善的调试替代方案 - purescript-debugger?精心设计的 VS Code 调试扩展/功能将是锦上添花。
解决方案
首先,您观察到的症状并不意味着第一行没有执行。它总是执行,由于控制台在 PureScript REPL 中的工作方式,您只是看不到它的输出。输出被吞没。可悲的是,这不是 REPL 的唯一问题。
log
您可以通过替换throwError
并观察始终抛出错误来验证第一行是否始终执行。或者,您可以让第一行修改可变单元格而不是写入控制台,然后检查单元格的内容。
最后,这只发生在 REPL 中。如果你把这个launchAff_
调用放在里面main
并运行程序,你总是会得到控制台输出。
现在到手头的实际问题:如何调试跟踪。
如果您负担得起,登录到控制台是可以的,但有一种更优雅的方式:Debug.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
如果您查看它的源代码,您会发现它与我在上面的示例中所做的完全一样。
可悲的是,trace
当异常发生时,它在 REPL 中对您没有帮助,因为它仍在打印到控制台,因此出于相同的原因它仍然会被吞没。
但即使它没有被吞下,输出也有点乱码,因为trace
实际上输出的是颜色(帮助你在其他输出中分辨出来),而 PureScript REPL 与颜色的关系很复杂:
> calculateSomething 37 5
←[32m'x = 37'←[39m
42
推荐阅读
- javascript - 如何在 Angular 中将标签与它们之外的表单字段相关联?
- authentication - 如何使路由仅在登录 asp.net core 2.1 后可用?
- javascript - 为什么放大和缩小第一次在 React js 中不起作用?
- php - 简化 PHP 中很长的 if 语句
- java - Java 抛出异常:此站点包含在另一个站点中:“/”
- java - 为什么使用 EnumMap 而不是 HashMap
- python-3.x - ImportError:无法在 Python 3.6 上导入名称“etree”
- html - 如何在 Laravel 5.6 中垂直显示可变数据?
- mysql - 在 MySQL 中获得第二高的薪水值
- php - 如何以非 root 用户身份运行 php-fpm 主进程?