Why this code snippet can't compile whereas `print(square(3,0))` is ok?

Viewed 52

Why this code snippet can't compile whereas print(square(3,0)) is ok?

function square(iteratorMaxCount,currentNumber)

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

print(square(3,0))

for i,n in square(3,0)
do 
   print(i,n)
end

The compiler complains that:

> $lua main.lua 1   1 lua: main.lua:13: attempt to call a number value
> stack traceback:  main.lua:13: in main chunk  [C]: in ?
1 Answers

for i,n in square(3,0) is equivalent to for i,n in 1,1 and this means you are attempting to call 1 which is not a function and results in your error attempt to call a number value.

The first value in the expression list after in in the for loop definition needs to be a function, such as pairs or ipairs which are used when working with tables or arrays. If you're using some custom iterator, like square in your code, you want to create a function that defines the iterator storing limits as up values and returns an anonymous function, A function that does this is called an iterator factory.

function square(iteratorMaxCount,currentNumber)
    return function()
        if currentNumber<iteratorMaxCount then
            currentNumber = currentNumber+1
            return currentNumber, currentNumber*currentNumber
        end
    end
end

print(square(3,0)())
print(square(3,0))

for i,n in square(3,0) do 
    print(i,n)
end

Alternatively you can pass initial state to the function by defining 2 more values in the for loop expression list, the invariant state and a control variable.

for i,n in square,3,0 do 
    print(i,n)
end

Suggested Reading:

Programming in Lua: 7.2 – The Semantics of the Generic for

Related Topics:

Programming in Lua: 4.3.5 – Generic for

Programming in Lua: 7.1 – Iterators and Closures

Programming in Lua: 7.3 – Stateless Iterators

Related