You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A rule for removing (converting) generalized iteration #203
An implementation I have done in the past converts the following:
forx, y, zininputdoprint(x, y, z)
end
into:
local_iterator=inputlocal_invariant, _controliftype(input) =="table" thenlocal_mt=getmetatable(input)
iftype(_mt) =="table" andtype(_mt.__iter) =="function" then_iterator, _invariant, _control=_mt.__iter(input)
else_iterator, _invariant, _control=pairs(input) -- !endendforx, y, zin_iterator, _invariant, _controldoprint(x, y, z)
end
This may not be 100% correct but could be a good starting point.
As it can't be determined statically whether the subject of iteration is (1) a plain table, (2) an iterator function, or (3) a table with an __iter metamethod defined, it is necessary to insert a runtime check.
Notes:
Using pairs(input) does not necessarily conform to the order of Luau generic iteration (for example, consecutive array indices starting from 1 go first)
Doesn't handle iterating over userdata (with __iter defined), which is supported by Luau
There may also be issues with accessing __iter if __metatable is set
I think I would go with something that injects this function and then wraps the generic for values. Something like this:
fork, vinobjdo--[[]]end-- would become the line below:fork, viniterLuau(obj) do--[[]]end
And the implementation I would inject would be something like the following snippet, which basically is a lua implementation of the Luau next function. I think the rule could have some kind of strategy field that would be used to tweak the generated iter function. For example it could drop the __iter if someone is sure that the metamethod check is not necessary.
That is true, I'll make sure to remove that. Now the remaining thing to figure out is where to dump a unique file to hold this function instead of duplicating it at the top of each file that uses a for loop.
That is true, I'll make sure to remove that. Now the remaining thing to figure out is where to dump a unique file to hold this function instead of duplicating it at the top of each file that uses a for loop.
I'd personally prefer it having on top of each file rather than having to commit an extra file that serves one specific purpose. Separation of concerns
Activity
phoriah commentedon Nov 28, 2025
Wouldn't
next,be a more elegant solution? Though I guess there would be an issue with string.gmatch for example, as it returns an iterator.jeparlefrancais commentedon May 19, 2026
I think I would go with something that injects this function and then wraps the generic for values. Something like this:
And the implementation I would inject would be something like the following snippet, which basically is a lua implementation of the Luau
nextfunction. I think the rule could have some kind of strategy field that would be used to tweak the generated iter function. For example it could drop the__iterif someone is sure that the metamethod check is not necessary.sircfenner commentedon May 19, 2026
I like this! A note on the
iterLuauTableimplementation - thetotalArgs ~= 1check is too permissive:is perfectly valid as generalized iteration over table
t- the extra values...are simply not used.jeparlefrancais commentedon May 21, 2026
That is true, I'll make sure to remove that. Now the remaining thing to figure out is where to dump a unique file to hold this function instead of duplicating it at the top of each file that uses a for loop.
phoriah commentedon May 22, 2026
I'd personally prefer it having on top of each file rather than having to commit an extra file that serves one specific purpose. Separation of concerns
phoriah commentedon Jul 29, 2026
Also
k == math.floor(k)might be faster than the modulo check