On Sunday, July 7, 2013, Dirk Laurie wrote:
If I am allowed to, as far as the "empty" question is concerned,
I can extract:
Andrew thinks:
- nil makes a fantastic "empty" sentinel value;
- one should emphasize and increase the usefulness of nil's
role as "empty," for which it is a natural fit.
The main thrust of Andrew's post deals with the concept of deleting
a value. That, I think, deserves a thread of its own.
Beautifully done.
If I may add a proposed implementation, which would allow the productive use of nils as "empty" values in tables, would avoid changing the defined behavior of the language, except for one small detail[*], and would not add any syntax or commands:
1: Table index assignment always results in a stored value, even if that value is nil, provided that the key does not have an explicit constructor.
t[{}] = nil -- nothing stored.
t[1] = nil -- nil at index 1
t.foo = nil -- nil at index foo
2: When rawset is called with 2 arguments `rawset(t, i)`, the value at the given index is deleted, not set to nil.
rawset(t, foo) --key and value at t.foo is deleted, not set to nil.
3: When the number of return values that are returned by rawget may be 0 or 1. 0 return values signifies that there was no value found at the index.
select('#', rawget(t, foo)) --> 0
--- OPTIONAL:
4: __index metamethod may return 0 or 1 value.
__index = function(t, i)
if select('#', rawget(t, foo)) == 0 then
return
else
return nil
end
end
-- tables with no __index metamethod return nil if the key is set to nil or if the key is not present, just as it does today.
5: __index metamethod may have an argument signature of `(t, ...)`, which may be used to determine the given index has no value.
__index = function(t, ...)
if select('#', ...) == 0 then
---same as before
6: Change `type` such that `type()` is a legal call (returns nil, not error).
6a: For extra credit (this is a feature addition) make `type` return `nil, undefined` when no value is received. This would be in place of todays behavior, which is an error. Then, this could be used in place of varargs and select.
--------------
I believe that, were these changes made (even without the optional changes), everything would be in place to be able to meaningfully use nils as values. Then, an array library could be built that used nils as "empty", but the behavior as defined today for ipairs and for sequences, in general, could remain as it is.
-- Andrew
[*] believe that __index is defined to always return 1 and only 1 value.