lua-users home
lua-l archive

Re: Lua 5.3 `ipairs` considered perilous

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 02/16/2016 10:19 AM, Dirk Laurie wrote:
Example 1. XML tables. These are lists in which the items
are either scalars or XML tables, and which also have some
"attributes", i.e. string-valued keys associated with scalar values.
The context is very often one in which the items take default
attributes from the containing value by specifying it as __index.
I've never seen this practice, and wouldn't desire it myself.
Example 2. Plugging holes in lists of numbers.
 x = setmetatable({5,9,nil,6,nil,nil,3,1},
 {__index = load"return 0/0",
 __len=load"return 8"})
 print(table.concat(x," "))
5 9 -nan 6 -nan -nan 3 1
Without that "index", you can't concatenate the table.
However, try this:
for k,v in ipairs(y) do print(k,v) end
and see what happens.
It's a little more code, but it works:
tlen = 8;
x = setmetatable({5,9,nil,6,nil,nil,3,1},
 {__index = function(t,k)
 if type(k)=="number" and k<=tlen then return 0/0; end
 end;
 __len = function() return tlen; end;
 });
Furthermore, if the # operator respects __index (section 3.4.7 is a little ambiguous on this, neither specifying that it does nor that it doesn't), neither the upvalue tlen nor the __len() function are necessary. In your example, __len also isn't necessary, i.e. this works although I don't think it can be relied upon based on the manual:
x = setmetatable({5,9,nil,6,nil,nil,3,1},
 {__index = function(t,k)
 if type(k)=="number" and k<=8 then return 0/0; end
 end;
 });
If only we still had __ipairs, neat solutions to the problem
would have been possible.
Solutions ("neat" is a matter of opinion) are still possible, see above example.
You didn't specify what would be your alternative "neat" solution if __ipairs() still existed. If you don't specify *both* __ipairs *and* __index, you would not have filled the holes, since x[3] would still return nil, while `for i,v in ipairs(x)` would produce 3,nan. So my guess is that your "neat" solution would have at least as much code as my "unkempt" one.
As it stands, the straightforward
numeric `for` is the only answer.
No it isn't [see above example] but even if it were, what's wrong with numeric `for`s? While I have no big problem with __ipairs, I do think that the default ipairs() should respect __index. Given that it does, there are only a tiny minority of cases when it is simpler to use __ipairs than __index, so it seems cleaner to remove it.
-- David

AltStyle によって変換されたページ (->オリジナル) /