lua-users home
lua-l archive

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

On Wednesday, July 3, 2013, Philipp Janda wrote:
Am 03.07.2013 22:10 schröbte Andrew Starks:
On Wed, Jul 3, 2013 at 2:32 PM, Philipp Janda <> wrote:
c is 3, no matter what empty() or multi() return. IMHO this would be even
more important if table access become vararg _expression_ lists:

     local a, b, c = t[ 1 ], t[ 2 ], t[ 3 ]

c should be equal to t[ 3 ] even if t[ 1 ] and t[ 2 ] do not exist.

Of course, but it would seem reasonable that:

exists(a) --> false
exists(b) --> false

No, the local statement defines the variables a, b, and c, and t[1] and t[2] are adjusted to a single value. So exists(a) and exists(b) should also return true, even if exists(t[1]) and exists(t[2]) are false.

exists(c) --> true
print(c == t[3]) --> true

could also happen. No?

      select( '#', baz, baz, baz, foo ) --> 4

      { 1, baz, 2, baz }        --> { 1, nil, 2 }

In the case of table access, I'd suggest that "nil" would be the default
return for all values, but that you could still call an exists-like
function on any index value.

select(1,({1,baz,2,nil})[2]) --> 0
select(1,({1,baz,2,nil})[4]) --> 1

So this would be an exception to the usual argument adjustment: If inside a
table constructor, do not adjust an empty list to a single nil, only
increment the index.

I think that non-existant table keys return "nil" as a value, by
default. This could be true, generally, as well, which would not be
what was contemplated, above.

The idea was that nonexistent table keys return nothing which in most cases would be adjusted to a single nil value, unless the field access happens at the end of a list (RHS of an assignment, argument list, or table constructor) ...

that is, this concept coexists well with the following behavior:

local foo
print(baz) -->nil

This would actually print just an empty line. print is a vararg function, and the undefined baz is at the end of the argument list, so no adjustment takes place ...

print(foo) -->nil
print(exists(baz)) -->false

t = {foo, baz, 3}

print(exists(t[1]),exists(t[2]), exists(t[3])) -->true, false, true

I don't see any wierdness to that...

I'm not sure this is worth it.

Do you see inconsistencies with the possibility that an argument
position would be undefined? Lua could always substitute "nil" in such
cases, but at least there would be a way to find out.

My objection is that we have multiple cases, where an _expression_ that evaluates to zero values is adjusted to a single nil value:

- RHS of an assignment (not last element): `local x, y = empty(), nil`
- argument list (not last element): `print( empty(), nil )`
- table constructor `t = { empty(), empty(), 3 }`
- operand of arithmetic expressions: `empty() + 1`
- indexing operand: `empty().x = 1`
- explicit parentheses: `(empty())`
- etc.

So if we want `{ empty(), empty(), 3 }` to end up as `{ <undef>, <undef>, 3 }` instead of `{ nil, nil, 3 }`, we would need an exception to the normal value adjustment rule ...

Hmm. Somewhere an adjustment is made so that position is honored, in order to maintain existing behavior. 

My suggestion is that when asked for the value's type, a default behavior for a table can still be to return nil, even if there is no key set for the given index. It doesn't store a value for that index, yet when asked it still says nil. 

As was previously suggested, a simple way to find out would be to extend type such that:
type({empty(), empty(),3})[2])
--> nil, undefined

Another syntactic trick may be too have lua do this:

local foo

select("#", foo) --> 1
select("#", (foo)) --> 1
select("#", baz) --> 1 -- today's behavior, intact thus far

select("#", (baz)) --> 0 -- new behavior. 

That is: parens around non-existent values are not promoted to nils, even in the middle of vararg (causes error).