[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Second class nil? Strong and weak nils in tables?
- From: Duck <duck@...>
- Date: Sat, 27 Oct 2007 12:16:51 +1000 (EST)
I know this is a regularly visited topic, so I am sure this suggestion
isn't new. But here we go.
You can't have nils in tables. Well, you can (since any uninitialised
field comes out as 'nil' by default) and you can't (since writing nil into
an existing field is formally given as the way to delete that field; PiL2,
p.15).
This is seen as a particular problem for vararg functions, since ...
(the list of varargs passed in) can legitimately and importantly include
nils which need to be accounted for explicitly. But {...} (the array of
varargs passed in) can't deal with this, since nil fields and missing
fields cannot be distinguished.
So, code which might gracefully and efficiently use {...} must fall back
ungracefully and less inefficiently (say the detractors) on select(), or
table.maxn(), to deal correctly with varargs.
But what if the __mode metakey of a table were extended to allow tables to
support strong or weak nils, as well as strong or weak keys and values? By
default, nils in tables would be weak, as they are now. But if the __mode
metakey contained "n", the table would have strong nils. 'Weak nils' mean
that nil is an implicit default value for uninitialised fields; 'strong
nils' mean that nil can explicitly be used as the value of any key in the
table.
Tables with strong nils would require all fields to be initialised
explictly, with nil an allowed value. Assigning nil to a field would not
delete it, but would simply set its value to nil. Accessing an
uninitialised field woud raise an error by default, instead of returning
an implicit nil. An explicit library call (e.g. table.remove() extended to
allow a field name, not just an index numer, as its second argument) would
be used to delete a field-value pair from a strong-nilled table.
Wouldn't this keep everyone happy?
Changing the semantics of {...} to make it produce a strong table would
surely please varargs users? Existing code using select('#',...) and
table.maxn({...}) would still work. Those who wanted to keep backward
compatibility would simply change the default __mode of the {...} table
back to weak-nilled. But when you wanted an array in which #table would
'just work' despite the presence of nils, you could have one. (And you
could use the __index metamethod to override the error()-raising side
effects for some or all missing fields, of course.)
If you just did nothing and ignored the feature, things would just to work
as usual, as long as tables were weak-nilled by default.
Discuss. (Please don't flame if this is an already-suggested and
long-torn-apart bad idea :)