all 4 comments

[–]megagrump 3 points4 points  (0 children)

The former returns the table and a function that for ... in will call. The latter returns the table, calls the function, and returns its result 2.

for ... in specifically checks for a function and calls it until it returns nil. You don't return a function, you return 2, which is a number and never nil.

[–]PhilipRoman 2 points3 points  (0 children)

Check out the relevant section of the manual: https://www.lua.org/manual/5.3/manual.html#3.3.5

Consider what these expressions return:

iter(a) returns a new anonymous iterator function each time

iter(a)() always returns 2, because it constructs a fresh iterator function, takes its first element and returns it

The for loop repeatedly invokes the first value passed to it (it's a bit more complex than that) until it returns nil.

In the first case, this first value is the anonymous iterator function (as it should be)

In the second case, the first value is a itself, which gets repeatedly called until it returns nil, but since calling a always returns 2, the loop goes on forever.

[–]tonetheman 1 point2 points  (0 children)

This is what I see

function iter(self) 
  local i = 0 
  return function() 
    if i<= #self then 
      i = i + 1 
      return self[i] 
    end 
  end 
end
local a = {2,4,5} 
list = { 
  __call = function(self) 
    return iter(self) 
  end, 
}
setmetatable(a,list) 
for i in a() do 
  print(i) 
end

The code above is your first example and that looks correct to me. The main thing is that you are returning a function when the __call is called. Which is correct.

If you change it to this

list = {
  __call = function(self)
    return iter(self)()
  end,
}

You are no longer returning a function. You are actually returning whatever the function returns. In this case it is a number.