在 julia 中抛出错误和返回错误之间的区别

lon*_*000 7 error-handling julia

在给定条件的情况下,这两段代码会导致抛出相同的错误:

function f1(x)
  if x > 2
    return x
  else
    return error("x <= 2")
  end
end

function f2(x)
  if x > 2
    return x
  else
    throw(error("x <= 2"))
  end
end
Run Code Online (Sandbox Code Playgroud)

当 x <= 2 时同时出现f1f2错误,但我找不到为什么更喜欢一个而不是另一个的任何差异。更进一步,这 3 段代码返回相同的:

error(2)
throw(2)
throw(error(2))
Run Code Online (Sandbox Code Playgroud)

是否有关于如何使用 throw 与直接返回错误的指南?

ffe*_*tte 6

error本身会引发错误。从文档

error(message::AbstractString)

使用给定的消息引发 ErrorException。

所以没有必要返回它(如在你的f1函数中)或自己抛出它(如在 中f2);在这两种情况下,异常都会error在您手写returnthrow什至到达之前抛出。

throw(error(2))和之间的比较也是如此error(2)throw这里没有用,这两个表达式应该做同样的事情(即使堆栈跟踪是相同的)。


关于error(2)vs throw(2),从表面上看,它们确实是在做同样的事情(堆栈跟踪略有不同):

julia> error(2)
ERROR: 2
Stacktrace:
 [1] error(::Int64) at ./error.jl:42
 [2] top-level scope at REPL[8]:1

julia> throw(2)
ERROR: 2
Stacktrace:
 [1] top-level scope at REPL[10]:1
Run Code Online (Sandbox Code Playgroud)

但这仅仅是因为 REPL 以在这种情况下无法区分的方式漂亮地打印错误。实际上,它throw会引发您作为参数传递的内容:在这种情况下是整数 2。而error字符串化它的参数并ErrorException在提升它之前将它包装在一个对象中。这可以通过捕获异常并执行dump它来看到:

julia> try
         error(2)
       catch e
         dump(e)
       end
ErrorException
  msg: String "2"

julia> try
         throw(2)
       catch e
         dump(e)
       end
Int64 2
Run Code Online (Sandbox Code Playgroud)

总之,我想说

  • error如果要引发ErrorExceptions,请使用s,它们是带有字符串形式的消息的通用异常。当错误注定要发生在人类身上时,这在 IMO 中是足够的。如果你这样做,只调用error; 不要returnthrow它。
  • throw当您想要控制引发的异常类型时使用。例如:throw(BoundsError(my_array, idx))。这样的异常可能更容易在堆栈上的某些函数中捕获和以编程方式处理。或者,如果没有被发现,它可能至少会向用户传达更具体的信息。