Define default values for function arguments

ripat picture ripat · May 16, 2011 · Viewed 58.9k times · Source

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.

Answer

Stuart P. Bentley picture Stuart P. Bentley · May 16, 2011

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 '#').