Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Error handling 正在使用lua';s错误(..,级别)反模式?_Error Handling_Lua_Lua 5.1 - Fatal编程技术网

Error handling 正在使用lua';s错误(..,级别)反模式?

Error handling 正在使用lua';s错误(..,级别)反模式?,error-handling,lua,lua-5.1,Error Handling,Lua,Lua 5.1,Lua5.1的API提供了一个函数,它接受一个字符串(错误消息)和一个“级别” 我的理解是,level允许您向上移动调用堆栈,因此可以提供更好的错误报告,尤其是在以API形式交付模块时 例如,假设用户使用x=nil调用api_函数(x)。这将是一个错误,但API直到对其代码进行了相当多的修改后才知道 它可能导致此调用堆栈: api_function(x) : user_file.lua:30 -> api_function

Lua5.1的API提供了一个函数,它接受一个字符串(错误消息)和一个“级别”

我的理解是,
level
允许您向上移动调用堆栈,因此可以提供更好的错误报告,尤其是在以API形式交付模块时

例如,假设用户使用
x=nil
调用
api_函数(x)
。这将是一个错误,但API直到对其代码进行了相当多的修改后才知道

它可能导致此调用堆栈:

api_function(x)                     : user_file.lua:30
  -> api_function                   : api.lua:20
    -> some_function                : api.lua:250
      -> handle_when_x_string       : api_string.lua:20
        -> error("value is nil")    : api_string.lua:66
如前所述,用户将看到类似于
api\u字符串的内容。lua:66错误:值为nil
,而他们真正想看到的是“nice”错误,
user\u文件。lua:30错误:值为nil
。(“这是我的错还是API中的错误?”)

现在,我们可以将代码更改为“弹出调用堆栈”

这将返回“nice”错误,但是,想象一下,当\u x_string更直接地调用
handle\u时(除了糟糕的API设计)

现在我们的“流行级别”是不正确的。也许在这个例子中,它会简单地弹出到顶部并停止尝试,但“不正确的级别”的原则至少仍然令人不舒服,它甚至可能弹出用户导致错误的位置

我可以看到一些解决方案:

  • 不要设置级别,只需假设用户足够聪明就能解决它
  • 将api入口点(
    api_函数
    &
    另一个api_fn
    )下方的任何内容包装在pcall中,捕获任何错误并使用已知的“良好”级别值重新冒泡
  • 不要在较低的api函数中出错,始终
    返回nil、error
    或类似的模式,然后在
    api_函数中检查该模式,并根据需要执行操作
我的问题是:

  • 返回错误的级别是否有问题?只是“是的,不管怎样”一个数字并希望它是好的,这看起来很糟糕
  • 如果这是一个问题,什么时候设置该级别是一个好的做法(超过0可能会禁用位置报告)
  • 哪种解决方案(如果有的话)是最佳实践?我应该如何编写更好的可维护代码?在pcall中包装似乎最简单,因为在测试时您仍然可以依赖“正常错误”,并且您的函数稍微简单一些,但在我看来,它似乎是一种反模式

在Lua中,使用
error()
来“冒泡”错误是非常罕见的。更常见的是返回
nil
,后跟一个描述错误的字符串,并让调用方决定函数失败是否是可以恢复的,是否应该重试,等等

与调用
error()
(这只是一个普通的函数调用)相比,它的开销更小,因此性能更高

过度使用
pcall
和转发错误是一个非常糟糕的主意。这只会让你的代码更难理解

返回错误的级别是否有问题?只是“是的,不管怎样”一个数字并希望它是好的,这看起来很糟糕

不,除了引起混乱。错误消息是有帮助的,如果你去“无论什么”他们不会。从实现的角度来看,没有风险:用于添加带有错误位置的消息。如果您走得太远,信息将被跳过:

函数foo()
错误(“我在哪里”,7)
结束
卢:我在哪里
--堆栈回溯:。。。
我通常只看到级别1和2,后者通常用于指示传递给函数的参数不正确。但这是我的观察,没有具体数据支持


至于剩下的问题,主要是基于意见。使用任何适合你和你的问题。
error()
nil
+消息都是合理的方法。您对它的研究做得很好,并且似乎对它有足够的理解来做出决定。

首先,您需要区分由于错误的API调用导致的错误和代码中的实际错误

如果
error
调用的目的是告诉API用户他们传递了错误的参数,那么您应该验证每个API函数中的参数,这样错误级别就可以知道,并且库的其他部分就知道它正在使用有效的参数。如果您最终得到一个复杂的验证函数层次结构,它们可以获取函数名和错误级别的参数。下面是一个关于如何使用错误级别的精心设计的示例:

local function lessThan100(x, funcName, errorLevel)
  if x >=100 then
    error(funcName .. ' needs a number less than 100', errorLevel)
  end
end

local function numLessThan100(x, funcName, errorLevel)
  if type(x) ~= 'number' then
    error(funcName .. ' needs a number', errorLevel)
  end
  lessThan100(x, funcName, errorLevel + 1)
end

-- API function
local function printNum(x)
  numLessThan100(x, 'printNum', 3)
  print(x)
end

如果
错误
调用代表代码中的错误,那么不要使用级别,因为您不知道是什么触发了错误。

这似乎是一个针对特定目的而存在的特定工具的例子。 从:

error函数还有一个附加的第二个参数,它给出 报告错误的级别;有了它,你可以责怪别人 否则将导致错误。例如,假设您编写了一个函数及其 第一项任务是检查是否正确调用了它:

然后,有人用错误的参数调用您的函数:

Lua将它的手指指向您的函数——毕竟,调用错误的是foo——而不是真正的罪魁祸首,调用方。 要更正此错误,请通知error您正在报告的错误 在调用层次结构中的级别2上发生(级别1是您自己的 功能):

没有一种语言是完美的,有时设计者会创建一个强大且潜在危险的工具来解决特定的问题。(例如,C#反射)在这种情况下,其目的似乎是报告发出调用的函数中的错误API调用,而不是报告接收调用的函数。因此,根据文档,级别1和2是唯一的预期级别,但这并不意味着其他用例不存在

您已经强调了(mis)使用此语言功能可能会导致比解决问题更多的问题的方式(即使用错误代码误导用户)
another_api_fn(x)                     : user_file.lua:44
  -> another_api_fn                   : api.lua:11
    -> handle_when_x_string           : api_string.lua:20
      -> error("value is nil", 5)     : api_string.lua:66
local function lessThan100(x, funcName, errorLevel)
  if x >=100 then
    error(funcName .. ' needs a number less than 100', errorLevel)
  end
end

local function numLessThan100(x, funcName, errorLevel)
  if type(x) ~= 'number' then
    error(funcName .. ' needs a number', errorLevel)
  end
  lessThan100(x, funcName, errorLevel + 1)
end

-- API function
local function printNum(x)
  numLessThan100(x, 'printNum', 3)
  print(x)
end