lua-users home
lua-l archive

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

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