Объект, используемый после in
, должен быть функцией, которая будет неоднократно вызываться универсальным циклом for
.
Я не уверен, что вы можете сделать таблицу или пользовательский объект вызываемым какфункции, но даже в этом случае проблема заключается в том, что ваш объект может иметь только одно внутреннее состояние итератора - то есть он не разрешит несколько итераций для одного и того же объекта (ни одновременно, ни последовательно), если только вы каким-то образом не сбросите его явно.
Как ответил Стюарт, вы можете использовать метаметод __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
Но часто у нас не будет чего-то подобного, тогда она получает большесложный.
Я думал об использовании сопрограмм здесь, но они все еще нуждаются в фабричном методе (которого мы хотим избежать).Это приведет к чему-то похожему на то, что написал Стюарт (т.е. сохранит состояние итератора где-то в самом объекте или в какой-либо другой переменной, связанной с объектом), и с помощью параметра и / или результата итераторов решит, когда создавать / очищатьитератор объект / состояние.
Здесь ничего не выиграно.