我注意到基本软件包使用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")
答案 0 :(得分:2)
error
意味着发生了一件不好的事情,因此对于大多数(即使不是全部)目的,它有多快也没关系,因为它表明程序无法正常工作。
也就是说,快速浏览一下代码足以合理地猜测error
比errorWithoutStackTrace
做的工作要严格得多(并且在{的基础上增加了withFrozenCallStack
{1}}代码的变体。读者可以自己确定是否使用基准测试。
这是error
和error
的定义:
https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Err.html#error
errorWithoutStackTrace
现在,这两个内部函数的定义如下:
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
”中)。