之后使用的对象in
必须是一个函数,该函数将被泛型for
循环重复调用。
我不确定您是否可以使表或用户对象像函数一样可调用,但即便如此,问题仍然是您的对象只能具有一个内部迭代器状态 - 即它不允许对同一个对象进行多次迭代(两者都不同时或顺序),除非您以某种方式明确地重置它。
正如 Stuart 所回答的那样,您可以__call
适当地使用元方法来返回迭代器,但是您必须编写
for obj in myObject() do
obj:foo()
end
这不是我们想要的。
在PiL中阅读更多内容,我发现 for 循环中使用了更多组件:不变的循环状态和控制变量的当前值,它们在每次调用中传递给迭代器函数。如果我们不在in
表达式中提供它们,它们将被初始化为nil
.
因此,我的想法是使用这些值来区分各个调用。
如果您可以next(element)
为您的集合创建一个函数,该函数为每个元素返回下一个元素,那么实现将很简单:
metatable.__call = function(_state, _last)
if(_last == nil) then
return obj:first()
else
return obj:next(_last)
end
end
但通常我们不会有这样的东西,然后它变得更加复杂。
我考虑过在这里使用协程,但是这些仍然需要工厂方法(我们要避免)。这将导致类似于 Stuart 所写的内容(即将迭代器状态保存在对象本身的某处或与对象相关的其他变量中),并使用参数和/或迭代器结果来决定何时创建/清理迭代器对象/状态。
这里什么都没赢。