Define default values for function arguments

FunctionLua

Function 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionripatView Question on Stackoverflow
Solution 1 - FunctionStuart P. BentleyView Answer on Stackoverflow
Solution 2 - FunctionjpjacobsView Answer on Stackoverflow
Solution 3 - FunctionStuart P. BentleyView Answer on Stackoverflow
Solution 4 - FunctionNineBlindEyesView Answer on Stackoverflow
Solution 5 - FunctionDejay ClaytonView Answer on Stackoverflow
Solution 6 - Functionuser15049586View Answer on Stackoverflow