为函数参数定义默认值
在 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
从技术上讲,有一个 b = b == nil and 7 or b
(应该在 false
是一个有效值的情况下使用,因为 false or 7
的结果是 7),但这可能不是你想要的。
如果你想要像 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
(返回给定参数列表中的单个值,或者使用 '#'
返回该列表的长度)。
目前我找到的唯一有意义的方式是像这样做:
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()
如果你的函数希望参数值既不是布尔值的 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]
]]
当然,可变参数会完全破坏使用它们的函数中函数参数的自动补全和代码检查。
简短的答案是这是最简单和最好的方式。在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
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
在我看来,没有其他方法。这就是 Lua 的思维方式:没有花哨的东西,除了一些语法糖之外,没有多余的方式去做简单的事情。