Search code examples
luareturn

How can a comma-separated return statement in Lua act as a function call?


I'm new to Lua and trying to figure out how the return statement in the squares function below is being used in the following code snippet:

function squares(iteratorMaxCount)
   return square,iteratorMaxCount,0
end

The square parameter in the return statement refers to a function with the following signature:

function square(iteratorMaxCount,currentNumber)

What's confusing me is that the return statement looks like it's returning three values. What I think it's actually doing, however, is passing iteratorMaxCount and 0 as the arguments to a square function call.

Can anyone explain to me what's happening with this syntax? How is this serving as a function call as opposed to returning three values? In my mind, it feels as though the return statement should be written return square(iteratorMaxCount, 0) as opposed to return square, iteratorMaxCount, 0. I know that this is obviously wrong, but I can't figure out why.

I've tried searching through the Lua Manual, Lua Reference Guide, and searching Google, but I can't seem to find anything that explains this particular syntax. Can anyone point me in the right direction, please?

Thanks in advance.

Full code below via Tutorialspoint

function square(iteratorMaxCount,currentNumber)

   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
      return currentNumber, currentNumber*currentNumber
   end

end

function squares(iteratorMaxCount)
   return square,iteratorMaxCount,0
end  

for i,n in squares(3)
do 
   print(i,n)
end

Solution

  • squares really does return three values, the first of which is a function. squares does not call square at all.

    The trick here is how the for ... in syntax works. In the Lua 5.3 Reference Manual, section 3.3.5 says:

    A for statement like:

    for var_1, ···, var_n in explist do block end
    

    is equivalent to the code:

     do
       local f, s, var = explist
       while true do
         local var_1, ···, var_n = f(s, var)
         if var_1 == nil then break end
         var = var_1
         block
       end
     end
    

    So the keyword "in" needs to be followed by three values:

    1. an "iterator function" for getting the variables in each iteration
    2. a "state" value to pass to the function each time
    3. an initial value to pass to the function the first time

    After the first time the function is called, the first value from the previous call is passed back into the next function call. When the first value returned from the function is nil, the for loop ends.

    So in this example, squares(max) is designed to be used after "in", using square as the iterator function, max as the "state", 0 as the initial value, and a number and its square as the loop data values.