[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua 5.3 `ipairs` considered perilous
- From: David Favro <lua@...>
- Date: Tue, 16 Feb 2016 15:05:14 -0500
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