The object used after in must be a function that will be called repeatedly by the general for loop.
I'm not sure that you can make the table or user object callable as a function, but even then the problem will be that your object can have only one internal state of the iterator - that is, it does not allow multiple iterations compared to the same object ( neither simultaneously, nor sequentially) if you somehow have not explicitly dropped it.
As Stuart replied, you could use the __call __call to return the iterator, but then you have to write
for obj in myObject() do obj:foo() end
This is not exactly what we want.
Reading is a bit more in PiL , I see that there are more components in the for loop: the state of the invariant loop and the current value of the control variable, which is passed to the iterator function in each call. If we do not provide them in the in expression, they are initialized to nil .
So my idea would be to use these values to distinguish between individual calls.
If you can create a next(element) function for your collection that returns the following for each element, the implementation will be simple:
metatable.__call = function(_state, _last) if(_last == nil) then return obj:first() else return obj:next(_last) end end
But often we would not have something like this, then it gets complicated.
I thought about using coroutines here, but this still needs the factory method (which we want to avoid). This would lead to something similar, as Stuart wrote (i.e. saving the iterator state somewhere in the object itself or in some other variable associated with the object), and using the parameter and / or result of the iterators to decide when to create / clean the object and the state of the iterator.
Nothing is won here.