如何解决引发错误时在堆栈跟踪中包含函数参数
在 Erlang 中,当引发错误时,我可以通过将第二个参数传递给 EntryDate LoanGiven LoanReceived
---------- --------------------------------------- ---------------------------------------
2020-12-03 11500.00 1000.00
来包含当前函数的参数:
error
这意味着参数将在堆栈跟踪中可见,这可以使调试更容易:
-module(foo).
-export([foo/2]).
foo(A,B) ->
error(something_went_wrong,[A,B]).
在 Erlang 和 Elixir 中,这会在函数子句错误时自动发生:
> foo:foo(1,2).
foo:foo(1,2).
** exception error: something_went_wrong
in function foo:foo/2
called as foo:foo(1,2)
defmodule Foo do
def foo(a,b) when false do
:ok
end
end
除了直接调用 > Foo.foo(1,2)
** (FunctionClauseError) no function clause matching in Foo.foo/2
The following arguments were given to Foo.foo/2:
# 1
1
# 2
2
foo.ex:2: Foo.foo/2
之外,有没有办法在 Elixir 中为显式引发的异常包含函数参数?我查看了 the documentation for Kernel.raise
并没有找到合适的。
解决方法
感觉像是逃避,但我相信这样做的首选方法是对消息中的变量使用 inspect/2
,例如
raise ArgumentError,message: "There was a problem with the inputs: #{inspect(a)} #{inspect(b)}"
# Yields:
# ** (ArgumentError) There was a problem with the inputs: "foo" "bar"
Elixir defexception docs 中的示例或多或少都做同样的事情,只是附加到自定义异常模块,例如:
defmodule ABError do
defexception [:message]
end
a = "foo"
b = "bar"
raise ABError,message: "There was a problem with the inputs: #{inspect(a)} #{inspect(b)}"
# Yields:
# ** (ABError) There was a problem with the inputs: "foo" "bar"
有了 Erlang 的背景,您或许能够更清楚地了解所有这些是如何通过 Exception module
,没有通用的方法可以做到这一点,因为 elixir 中的异常只是一个结构体。另一方面,这为您提供了灵活性,例如,用于上述 FunctionClauseError
,that is defined as
defexception [:module,:function,:arity,:kind,:args,:clauses]
因此,当编译器引发它时,message
被构造为包含通过原始错误传递的 arguments。
为了实现相同的目的,通常使用 Kernel.defexception/1
定义自定义异常,接受参数并从 message/1
行为实现 Exception
和 blame/2
回调。一个很好的例子是 FunctionClauseError
实现的来源,我在上面链接。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。