以下引用摘自 Julia 文档:
Julia 中的异常处理是使用
而不是try — catch — finally
完成的。与 Python 相比,不建议在 Julia 中将异常处理作为正常工作流程的一部分(与 Python 相比,Julia 在普通控制流方面更快,但在异常捕获方面较慢)。try — except — finally
这就提出了一个问题 - 在 Julia 程序中处理错误状态的推荐方法是什么?
我知道的其他方式
Result
(或有时,Option
)类型,例如 Rust之前在此站点和其他地方都曾进行过讨论,深入讨论了为什么 (1) 是一个坏主意,但是 Julia 文档中的引用似乎表明在 Julia 程序中处理错误状态的推荐方法是返回任意整数错误代码。我觉得这很令人惊讶,并怀疑我的解释不正确。
正如其他人所评论的,
try
、catch
和finally
流程的替代方案不是直接替代方案,而是预先重构代码以处理错误原因。
由于这是一个非具体的答案,因此对不同的控制流进行基准测试可能会有所帮助,以确定此重构是否值得重构的时间投资。
下面是一个以两种方式编写的简单函数:一种使用
try
来检测越界错误,另一种使用 if
来避免越界错误。请注意,这些函数在局部变量大小、时间复杂度等方面具有可比性,它们唯一真正的区别是控制流的选择,其中“if 函数”需要一个额外的相等性检查。
julia> function useTry()
count = 0
sizeOfVector = 50
myVector = zeros(sizeOfVector) .+ 1 # create a vector of ones
for i in 1:100
try # try to add the ith element to count
count += myVector[i]
catch # if i is out of bounds, do nothing
nothing
end
end
return count == 50
end
useTry (generic function with 1 method)
julia> function avoidTry()
count = 0
sizeOfVector = 50
myVector = zeros(sizeOfVector) .+ 1 # create a vector of ones
for i in 1:100
if i <= sizeOfVector # if possible, add the ith element to count
count += myVector[i]
else # if i is out of bounds, do nothing
nothing
end
end
return count == 50
end
avoidTry (generic function with 1 method)
julia> using BenchmarkTools
julia> @btime useTry()
308.300 μs (152 allocations: 4.88 KiB)
true
julia> @btime avoidTry()
315.929 ns (2 allocations: 992 bytes)
true
因此,使用 BenchmarkTools 的
@btime
(本质上是内置 @time
的改进(平均多次运行)版本),avoidTry
比 useTry
快 975.85 倍。现在,这里有一些重要的警告:运行时将根据设备和当前设备使用情况而有很大差异,并且这两个功能仍然具有相当的性能。话虽这么说,更大数量的分配表明不同设备之间可能存在类似的性能差异。
这个小测试虽然说明了问题,但并不是故事的全部。如果您想要进行与此类似的测试,则必须使用与您的预期用例类似的函数来测试运行时。希望这能让您相信 Julia 文档并没有在性能差异方面撒谎,并且在适用时可能会避免
try
。