[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 :)