[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: [ANN] Lua 5.4.0 (work1) now available
- From: Oliver Kroth <oliver.kroth@...>
- Date: Thu, 15 Mar 2018 08:32:49 +0100
Am 14.03.2018 um 19:24 schrieb Roberto Ierusalimschy:
Experiment: There is a type 'nil' and two predefined values 'empty'
and 'undef' both visible at the Lua level. If LUA_NILINTABLES is not
defined, they are the same and behave just like the value 'nil' does.
Otherwise there is a difference. 'undef' is actually quite close to
the present value 'nil': it is what too-short tuples are filled with;
it defines where a boundary in a table is. 'empty' behaves like the
empty value in the current implementation.
If we do 'nil=empty', the work1 implementation could also serve as an
implementation of this model.
The question is: is this model really conceptually worse? Would it not
in fact be quite useful to have access to both these values at the Lua
level?
The problems I am trying to solve are these:
1) A constructor like {x, y, z} should always create a sequence with
three elements. A constructor like {...} should always get all arguments
passed to a function. A constructor like {f(x)} should always get
all results returned by the function. '#' should always work on these
tables correctly.
2) A statement like 't[#t + 1] = x' should always add one more element
at the end of a sequence.
These are what confuse people all the time, these are what start new
rounds of discussions around '#'.
Once 'empty' and 'undef' are values, you break all those properties.
I think we cannot use a value to represent the absence of a value, no
matter how many no-value values we add. It is a contradiction. Several
languages followed this path, always with bad results.
Lua already uses a value for the absence of a value: nil.
nil is destructive, it removes the previous value and the key form a
table when assigned.
That is what the synthetic x=undef operation shall do in future.
I like to propose to keep original meaning of nil.
And add a new value of the same 'nil' type, let's name it "empty" for now.
"empt"y is a representation of the fact that there is no value at that
place in the table, but keeps the key bound to the table.
"empty" = "No water in the bucket"
"nil" = "not even a bucket"
A constructor {x,y,z} should use "empty" to fill a gap if it gets nil.
so {"a", true, 42, nil, "Hello"} constructs:
{
[1] = "a",
[2] = true,
[3] = 42,
[4] = empty,
[5] = "Hello"
}
That would fulfil your statement 1)
what would { 1, 2, nil, nil } produce?
At first thought I would assume { 1, 2, empty, empty }.
What would
t = {}
t[1], t[2], t[3], t[4] = 1, nil, nil, 4
produce ?
I would guess:
t ==
{
[1] = 1,
[4] = 4
}
These comparisons should be true: type(empty) == type(nil) == "nil"
Maybe also: empty == nil ( in the same sense that 1.0 == 1 )
Regarding 2):
When I add "" to a string, the string length does not increase either.
So, t[ #t +1 ] = nil is fine not to change t, and thus #t
t[ #t +1 ] = empty would change it by creating an "empty bucket"
Long story short: I do not disagree with having a key conserving non-value.
But that should be the new item.
Please do not change the semantics of "nil", and introduce an "undef"
that does what the "nil" did before.
--
Oliver