Define default values for function arguments
FunctionLuaFunction Problem Overview
In the Lua wiki I found a way to define default values for missing arguments:
function myfunction(a,b,c)
b = b or 7
c = c or 5
print (a,b,c)
end
Is that the only way? The PHP style myfunction (a,b=7,c=5)
does not seem to work. Not that the Lua way doesn't work, I am just wondering if this is the only way to do it.
Function Solutions
Solution 1 - Function
If you want named arguments and default values like PHP or Python, you can call your function with a table constructor:
myfunction{a,b=3,c=2}
(This is seen in many places in Lua, such as the advanced forms of LuaSocket's protocol modules and constructors in IUPLua.)
The function itself could have a signature like this:
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
Any values missing from the table of parameters will be taken from the __index
table in its metatable (see the documentation on metatables).
Of course, more advanced parameter styles are possible using table constructors and functions- you can write whatever you need. For example, here is a function that constructs a function that takes named-or-positional argument tables from a table defining the parameter names and default values and a function taking a regular argument list.
As a non-language-level feature, such calls can be changed to provide new behaviors and semantics:
- Variables could be made to accept more than one name
- Positional variables and keyword variables can be interspersed - and defining both can give precedence to either (or cause an error)
- Keyword-only positionless variables can be made, as well as nameless position-only ones
- The fairly-verbose table construction could be done by parsing a string
- The argument list could be used verbatim if the function is called with something other than 1 table
Some useful functions for writing argument translators are unpack
(moving to table.unpack
in 5.2), setfenv
(deprecated in 5.2 with the new _ENV
construction), and select
(which returns a single value from a given argument list, or the length of the list with '#'
).
Solution 2 - Function
In my opinion there isn't another way. That's just the Lua mentality: no frills, and except for some syntactic sugar, no redundant ways of doing simple things.
Solution 3 - Function
Technically, there's b = b == nil and 7 or b
(which should be used in the case where false
is a valid value as false or 7
evaluates to 7), but that's probably not what you're looking for.
Solution 4 - Function
The only way i've found so far that makes any sense is to do something like this:
function new(params)
params = params or {}
options = {
name = "Object name"
}
for k,v in pairs(params) do options[k] = v end
some_var = options.name
end
new({ name = "test" })
new()
Solution 5 - Function
If your function expects neither Boolean false
nor nil
to be passed as parameter values, your suggested approach is fine:
function test1(param)
local default = 10
param = param or default
return param
end
--[[
test1(): [10]
test1(nil): [10]
test1(true): [true]
test1(false): [10]
]]
If your function allows Boolean false
, but not nil
, to be passed as the parameter value, you can check for the presence of nil
, as suggested by Stuart P. Bentley, as long as the default value is not Boolean 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]
]]
The above approach breaks when the default value is Boolean 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]
]]
Interestingly, reversing the order of the conditional checks does allow Boolean false
to be the default value, and is nominally more performant:
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]
]]
This approach works for reasons that seem counter-intuitive until further examination, upon which they are discovered to be kind of clever.
If you want default parameters for functions that do allow nil
values to be passed, you'll need to do something even uglier, like using variadic parameters:
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]
]]
Of course, variadic parameters completely thwart auto-completion and linting of function parameters in functions that use them.
Solution 6 - Function
Short answer is that it's simplest and best way . in lua , variables by default equal with nil
. this means if we don't pass argument to lua functions ,the argument is exits but is nil
and lua programmers uses of this lua attribute for set the default value .
also it's not a way for set default value but you can use following function
this function create a error is you don't pass values to arguments
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
but it's not a good way and better is don't use of this function
and in diagrams shows optional argument in [,arg]
function args(a1 [,a2])
-- some
end
function args ( a1 [,a2[,a3]])
-- some
end