lua-users home
lua-l archive

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




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