为函数参数定义默认值

在 Lua 的 wiki 中,我找到了一种定义缺少参数默认值的方法:

function myfunction(a,b,c)
    b = b or 7
    c = c or 5
    print (a,b,c)
end

这是唯一的方法吗?PHP 风格的 myfunction(a,b=7,c=5) 似乎不起作用。并不是说 Lua 的方式不起作用,只是想知道这是否是唯一的方法。

原文链接 https://stackoverflow.com/questions/6022519

点赞
stackoverflow用户513763
stackoverflow用户513763

在我看来,没有其他方法。这就是 Lua 的思维方式:没有花哨的东西,除了一些语法糖之外,没有多余的方式去做简单的事情。

2011-05-16 20:08:56
stackoverflow用户34799
stackoverflow用户34799

从技术上讲,有一个 b = b == nil and 7 or b (应该在 false 是一个有效值的情况下使用,因为 false or 7 的结果是 7),但这可能不是你想要的。

2011-05-16 20:42:35
stackoverflow用户34799
stackoverflow用户34799

如果你想要像 PHP 或 Python 一样使用具名参数和默认值,你可以使用表构造函数来调用函数:

myfunction{a,b=3,c=2}

(在 Lua 的许多地方都可以看到这种用法,例如LuaSocket的高级协议模块IUPLua的构造函数等。)

函数本身可以具有以下形式:

function myfunction(t)
    setmetatable(t,{__index={b=7, c=5}})
    local a, b, c =
      t[1] or t.a,
      t[2] or t.b,
      t[3] or t.c
    -- function continues down here...
end

表参数中缺少的任何值都会从其元表的__index表中获取(请参阅关于元表的文档)。

当然,还可以使用表构造函数和函数来实现更高级的参数样式 -- 您可以编写任何需要的代码。例如,这里是一个构造函数的示例,它使用一个定义参数名称和默认值的表和一个使用常规参数列表的函数来构造一个名称汇总、位置汇总或两者都可以的函数。

作为一种非语言级别的功能,这些调用可以修改以提供新的行为和语义:

  • 变量可以被定义成接受多个名称
  • 位置变量和关键字变量可以交错出现,并且同时定义这两种变量可以优先考虑其中任何一种(或导致错误)
  • 可以创建只能使用关键字而不能使用位置的变量,也可以创建只能使用位置而不能使用名称的变量
  • 可以通过解析字符串来完成相当冗长的表构造
  • 如果函数被使用除 1 个表以外的参数调用,那么可以直接使用该参数列表

编写参数转换器的一些有用函数包括unpack(在 5.2 版本中移到了table.unpack),setfenv(在 5.2 版本中已被弃用,使用新的 _ENV 结构代替),以及select(返回给定参数列表中的单个值,或者使用 '#' 返回该列表的长度)。

2011-05-16 20:59:48
stackoverflow用户845673
stackoverflow用户845673

目前我找到的唯一有意义的方式是像这样做:

function new(params)
  params = params or {}
  options = {
    name = "对象名称"
  }

  for k,v in pairs(params) do options[k] = v end

  some_var = options.name
end

new({ name = "测试" })
new()
2012-04-21 00:53:33
stackoverflow用户111948
stackoverflow用户111948

如果你的函数希望参数值既不是布尔值的 false 也不是 nil,那么你建议的方法就很好:

function test1(param)
  local default = 10
  param = param or default
  return param
end

--[[
test1(): [10]
test1(nil): [10]
test1(true): [true]
test1(false): [10]
]]

如果你的函数允许布尔值的 false,但不允许 nil 作为参数值传递,你可以按照 Stuart P. Bentley 的建议检查 nil 的存在,只要默认值不是布尔值的 false 即可:

function test2(param)
  local default = 10
  param = (param == nil and default) or param
  return param
end

--[[
test2(): [10]
test2(nil): [10]
test2(true): [true]
test2(false): [false]
]]

当默认值是布尔值的 false 时,上述方法失效:

function test3(param)
  local default = false
  param = (param == nil and default) or param
  return param
end

--[[
test3(): [nil]
test3(nil): [nil]
test3(true): [true]
test3(false): [false]
]]

有趣的是,如果将条件检查的顺序反过来,布尔值的 false 就能成为默认值,并且在性能上优于其他方法:

function test4(param)
  local default = false
  param = param or (param == nil and default)
  return param
end

--[[
test4(): [false]
test4(nil): [false]
test4(true): [true]
test4(false): [false]
]]

这种方法的实现看起来令人迷惑,直到仔细研究后才发现其巧妙之处。

如果你想为允许传递 nil 值的函数设置默认参数,那么你需要使用更丑陋的方法,如使用可变参数:

function test5(...)
  local argN = select('#', ...)
  local default = false
  local param = default
  if argN > 0 then
    local args = {...}
    param = args[1]
  end
  return param
end

--[[
test5(): [false]
test5(nil): [nil]
test5(true): [true]
test5(false): [false]
]]

当然,可变参数会完全破坏使用它们的函数中函数参数的自动补全和代码检查。

2021-02-02 05:00:12
stackoverflow用户88888888
stackoverflow用户88888888

简短的答案是这是最简单和最好的方式。在lua中,默认情况下变量等于 nil。这意味着如果我们没有向lua函数传递参数,参数是存在的,但是为 nil,lua程序员使用这个lua属性来设置默认值。

这不仅是设置默认值的方法,还可以使用以下函数

如果您没有将值传递给参数,则该函数会创建错误

function myFn(arg1, arg2)
err = arg1 and arg2
if not err then error("argument") end
-- or
if not arg1 and arg2 then error("msg") end

但这不是一个好方法,最好不要使用这个函数

在图表中显示可选参数 [,arg]

function args(a1 [,a2])
-- some
end
function args ( a1 [,a2[,a3]])
-- some
end
2021-04-30 16:34:17