lua-users home
lua-l archive

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


Another possible extension of the argument lists for function calls would be to allow parameters to be numbered explicitly:

   fun( [1] = anyexpression, [2] = anyexpression, [10] = anyexpression, )


Here again the single comma used after "anyexpression" means it is downcasting it to a single value or nil.
But you can pass parameters positionnally and even override them:

Here the "anyexpression" allows overwriting the 3 parameters [1]=a, [2]=b, and [3]=c (as well as parameters [4], [5] or at higher index)
   fun( a, b, c, [1] = anyexpression )

Here the "anyexpression" followed by a single comma allows overwriting only the parameters [1]=a with the first value in "anyexpression" (or nil if it has no value in its output list)
   fun( a, b, c, [1] = anyexpression, )

Using explicitly numbered parameters also allows interesting things in programs, such as passing a default list of numbered parameters, and explicitiy override any one of them conditionally at a variable index:
   fun( a, b, c, [index] = anyexpression, )

The condition is that "index" must be a non-zero integer smaller than the maximum allowed length for arguments (it depends on the implementation), but it can be higher than 3 (the number of values explicitly indicated in "a, b, c,"). If the index is zero or negative the downcasted single value from "anyexpression" (or nil) will not be stored in an effective parameter. If the index is not an integer number, or is any other type or nil, an error will be thrown. (Note that within table constructors between "{}", keys are less restricted in type and allow any number value; not just integers, only the nil key is not permitted, but you can overwrite some keys; within arguments lists for function calls, keys must be strictly positive integers, but are not necessarily a sequence from 1 to N as some indexed arguments may have a nil value).

Here the "anyexpression" followed by a double comma allows overwriting parameters [1]=a and any higher-ranked parameter
   fun( a, b, c, [1] = anyexpression,, )
Same thing with
   fun( a, b, c, [1] = anyexpression1,,anyexpression2 )
where "anyexpression1,,anyexpression2" forms a merged _expression_ list

But with
   fun( a, b, c, [1] = anyexpression,,anyexpression2, )
the merged list "anyexpression1,,anyexpression2" is created but its result is downcasted to a single value (or nil), which will be the first value returned in "anyexpression1" if there's one, otherwise the first value returned in "anyexpression2" if there's one, or otherwise nil.

The old Lua "trick" allowing to pack variable lists and merging them into a longer list is disallowed when using a single comma between them: you need to explicitly use the double comma...

Most programs do not want to depend on the old Lua trick with expressions lists (in arguments lists, or in table constructors). Using a final single comma at end of an arguments list also means that the last specified _expression_ will always be downcasted to a single value (or nil).

So: type(('A').byte(2)) may still (eventually) raise the error "missing parameter",
But: type(('A').byte(2),) will never raise that error as there is always at least one value provided which will be nil (this syntax is much clearer than using surrounding parentheses!)



Le lun. 6 sept. 2021 à 19:53, Paul K <paul@zerobrane.com> a écrit :
> The problem is that `('A':byte(2)` actually does not return `nil` in its list of upvalues, it just returns an empty list:

You can wrap it into parentheses to force `nil` if that's what's
needed in this case:

print(type( ( ('A'):byte(2) ) ))

This prints "nil" for me in all Lua versions 5.1+

Paul.

On Mon, Sep 6, 2021 at 9:19 AM Philippe Verdy <verdyp@gmail.com> wrote:
>
> The Lua builtin function "type(value)" unexpectedly signals an error (sometimes but not always) when the argument value is nil.
>
> This occurs when the value nil is the result of a function call, and not a simple variable containing nil or the constant nil. This is incoherent !
>
> That error is wrong. `type(nil)` or `type()` or `type(f())` (where `f()` returns nil or nothing), or `type(nil, 'dummy')` or `type(...)` (called from inside a function called without parameters or with a nil parameter in first position of the varaible argument list) should return 'nil' in all cases.
>
> E.g. run in a Lua console:
>
> val = ('A'):byte(1); typ = type(val); print typ ..'=' ..  tostring(val); print type(('A'):byte(1))
> --> number=65
> --> number
> val = ('A'):byte(2); typ = type(val); print typ .. '=' .. tostring(val); print type(('A'):byte(2))
> --> nil=nil
> --> Error: bad argument #1 to 'type' (value expected).
>
> The problem is that `('A':byte(2)` actually does not return `nil` in its list of upvalues, it just returns an empty list:
> * when assigning an empty list to a variable, that variables get `nil` (with the correct type).
> * when passing the empty list returned by a function to `type()`, this function gets no parameter and incorrectly signals an "error".
>
> Yes the builtin `type(value)` function "requires" at least one argument, but that argument in first position CAN be `nil`. So it may not be passed at all and the first argument should be initialized with the `nil` value, and the builtin `type(value)` function SHOULD return the string `"nil"`, without any error (which I think is a very legacy behavior of very old versions of Lua before major changes in how lists of values were passed and returned through function calls).
>
> And the builtin `string.byte(index)` function SHOULD also be fixed to return a true `nil` for a given index past the end of string, and not an empty list (or this should not make any difference for calling type()).
>
>