lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Fri, Jul 14, 2017 at 2:10 AM, Roberto Ierusalimschy <roberto@inf.puc-rio.br> wrote:

> The syntax
>
>   function foo (a,b,c)
>
> can be considered basically a sugar for
>
>   function foo (...)  local a,b,c = ...

There is more than sugar to that, because there is a distinction between a vararg and non-vararg function in Lua:

local function f1(...)
  print(select('#', ...))
end

local function f2(a, b)
  print(select('#', ...))
end

f1(1)
f2(1)

The above does not compile, producing "cannot use '...' outside a vararg function near '...'" in the body of f2.

And even if that compiled, then select(') would have to behave differently in those two cases, because it should skip non-vararg arguments.

The other difference, which is the subject of this thread, is that ordinary functions have the nil substitution as part of the language, while vararg functions are free to emulate that behaviour or do something else. In the pure Lua world, the emulation follows naturally, unless the programmer gets smart about counting the number of arguments with select(). In the C underworld, it is easier for the programmer to do "something else", because the extra "none" type makes that possible without counting the number of arguments. Even when this is not intended, this is a mistake that is easy to make (I have done that myself and seen others do, too).

This behaviour is confusing for Lua programmers when some functions, ostensibly documented as non-vararg, do not behave as ordinary Lua functions. For a Lua programmer it is frequently impossible or at least difficult to say whether a given function is implemented in C or in Lua, even if these differences are understood.

To make matters worse, advanced programmers, like you and LHF, find the C-function behaviour so natural that they assume everybody else understands and expects that. In this very thread, both of you silently assumed that setmetatable(), despite not being documented as vararg, is permitted to behave as if it were vararg. I think the disconnect between the expectations is what this thread is really about.


Cheers,
V.