我注意到基础包使用errorWithoutStackTrace
来实现很多功能。以下两个定义之间有一些性能差异吗?
head :: [a] -> a
head (x:_) = x
head [] = errorWithoutStackTrace ("Prelude.head: empty list")
head :: [a] -> a
head (x:_) = x
head [] = withFrozenCallStack $ error ("Prelude.head: empty list")
最佳答案
error
意味着发生了不好的事情,因此对于大多数(如果不是全部)目的来说,速度有多快并不重要,因为它表明程序无法运行。
也就是说,快速浏览一下代码就足以合理地猜测 error
严格执行比 errorWithoutStackTrace
更多的工作(通过将 withFrozenCallStack
添加到代码的 error
变体中,情况变得更加复杂)。通过基准来确认这一点留给读者作为练习。
这是 error
的定义和errorWithoutStackTrace
:
https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Err.html#error
error s = raise# (errorCallWithCallStackException s ?callStack)
errorWithoutStackTrace s = raise# (errorCallException s)
现在这两个内部函数定义如下:
errorCallException :: String -> SomeException
errorCallException s = toException (ErrorCall s)
errorCallWithCallStackException :: String -> CallStack -> SomeException
errorCallWithCallStackException s stk = unsafeDupablePerformIO $ do
...
return $ toException (ErrorCallWithLocation s stack)
请注意,两者本质上都是 toException (something s)
,但是errorCallWithCallStackException
还有更多的代码来处理堆栈(在“...
”中)。
关于performance - 当没有 HasCallStack 时,errorWithoutStackTrace 会比 error 更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57492550/