[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Why is implicit and explicit 'nil' treated differently?
- From: Coda Highland <chighland@...>
- Date: Mon, 20 Apr 2015 06:30:27 -0700
On Mon, Apr 20, 2015 at 6:24 AM, Robert Virding <rvirding@gmail.com> wrote:
> On 19 April 2015 at 00:19, Andrew Starks <andrew.starks@trms.com> wrote:
>>
>>
>>
>> On Saturday, April 18, 2015, Jan Behrens
>> <jbe-lua-l@public-software-group.org> wrote:
>>>
>>> On Sat, 18 Apr 2015 21:45:01 +0300
>>> <tonyp@acm.org> wrote:
>>>
>>> > As you can see in the sample code below, print does not show the
>>> > implicit nil (when it is last in the list of things to print), yet it
>>> > shows the explicit one. However, in every other regard, nil seems to
>>> > behave the same in both cases.
>>> >
>>> > Can someone explain why there is a difference in 'nil' treatment
>>> > between these two? (I can see the compiler produces slightly
>>> > different code for each case but if they are equivalent, shouldn?t it
>>> > produce the exact same code for both cases?)
>>>
>>> It will be shown if you write:
>>>
>>> print(implicit()==nil, implicit(), implicit() or 'hidden')
>>> --> true nil hidden
>>>
>>> or
>>>
>>> print(implicit()==nil, implicit() or 'hidden', (implicit()))
>>> --> true hidden nil
>>>
>>> Generally "nil" and "none" (none = no value) are distinct when you call
>>> a function or return from a function. However, "none" gets implicitly
>>> converted to "nil" if you store it in a variable (or table) or if you
>>> put parenthesis around it (or use it in an expression where a single
>>> value is expected).
>>>
>>> If you use a function call as last(!) argument to another function
>>> call, e.g. f(arg1, arg2, g()), then multiple arguments returned from
>>> the last function will be passed to the outer function:
>>>
>>> function g()
>>> return "Hello", "World"
>>> end
>>>
>>> print("Note:", g())
>>> --> Note: Hello World
>>>
>>> That's why
>>>
>>> print(implicit()==nil, implicit() or 'hidden', implicit())
>>>
>>> won't print "nil", because implicit() is last in the argument list,
>>> which means that any variable number of return values (possibly zero
>>> return values) will be passed to the print function in addition to the
>>> two first arguments.
>>>
>>> >
>>> > And, is the difference evident only in print or elsewhere also?
>>>
>>> I think "print" and "select" are the two notable cases. You can use
>>> "select" to write your own functions to distinguish between "nil" and
>>> "none":
>>>
>>> function test(...)
>>> if select("#", ...) == 0 then
>>> return "no value given"
>>> elseif ... == nil then
>>> return "nil value given"
>>> else
>>> return "non-nil value given"
>>> end
>>> end
>>>
>>> test()
>>> --> no value given
>>> test(nil)
>>> --> nil value given
>>> test(false)
>>> --> non-nil value given
>>>
>>> >
>>> > I?m mostly interested if I should expect the exact same execution
>>> > path for code receiving either nil, or not? Because obviously print
>>> > has a different execution for each case.
>>>
>>> If you store a return value in a local variable or table, then "none"
>>> always gets automatically converted to "nil". If you want to perform
>>> this conversion explicitly, use parenthesis. This is also helpful to
>>> truncate a variable number of return values. Compare:
>>>
>>> print("Pos:", string.find("Hello World", "World"))
>>> --> Pos: 7 11
>>>
>>> print("Pos:", (string.find("Hello World", "World")))
>>> --> Pos: 7
>>>
>>>
>>> >
>>> > Thank you.
>>>
>>> Kind Regards,
>>> Jan Behrens
>>>
>>>
>>> >
>>> > function implicit()
>>> > return --implicit nil
>>> > end
>>> >
>>> > function explicit()
>>> > return nil --explicit nil
>>> > end
>>> >
>>> > print(implicit()==nil,implicit() or 'hidden',implicit())
>>> > print(explicit()==nil,explicit() or 'shown',explicit())
>>> > print(implicit() == explicit())
>>> >
>>> > --- And here?s what the compiler output looks like for the two
>>> > functions ---
>>> >
>>> > function <implicit> (2 instructions at 004CC030)
>>> > 0 params, 2 slots, 0 upvalues, 0 locals, 0 constants, 0 functions
>>> > 1 [2] RETURN 0 1
>>> > 2 [3] RETURN 0 1
>>> >
>>> > function <explicit> (3 instructions at 004CE790)
>>> > 0 params, 2 slots, 0 upvalues, 0 locals, 0 constants, 0 functions
>>> > 1 [6] LOADNIL 0 0
>>> > 2 [6] RETURN 0 2
>>> > 3 [7] RETURN 0 1
>>>
>>
>> There is one other case where nil/none appear. It almost never matters,
>> but it thwarted me from being too creative with tables: __index is always
>> adjust to one return value. So:
>>
>> __index = function(t, i, x)
>> --x is always absent (empty/nil), btw. This would almost certainly
>> never matter, but it's true. I'm not sure how I know this, actually.it
>> wouldn't happen from trying `t[1, 2]`, because that's an error. Anyway...
>> end
>>
>> f = function()
>> end
>>
>> print (select("#", __index()), select("#", f()))
>> -->1 0
>>
>> So you can never signal the difference between nothing and `nil` from your
>> index metamethod. Again, not complaining, I'm just sayin'.
>>
>
> Where does 'none' come from? I cannot find any mention of it in the 5.2
> manual.
>
> Robert
>
>
(Heads up, don't top-post on lua-l.)
The name is an invention for the sake of this discussion. The manual's
discussion is about how different numbers of return values are
handled. Specifically, a function can return any number of values,
from zero to however much can fit on the stack, and the return values
are coerced to a single value (nil if the function returned zero
values) if the results are forced into a context that only accepts a
single value (such as an expression or a non-final parameter to a
function call).
/s/ Adam
- References:
- Varargs efficiency, Soni L.
- Re: Varargs efficiency, Sean Conner
- Re: Varargs efficiency, Soni L.
- Re: Varargs efficiency, Tim Hill
- Re: Varargs efficiency, Soni L.
- Re: Varargs efficiency, Hisham
- Why is implicit and explicit 'nil' treated differently?, tonyp
- Re: Why is implicit and explicit 'nil' treated differently?, Jan Behrens
- Re: Why is implicit and explicit 'nil' treated differently?, Andrew Starks
- Re: Why is implicit and explicit 'nil' treated differently?, Robert Virding