lua-users home
lua-l archive

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


Hello,

Currently, when a vararg function needs to know the number of vararg
parameters it got, one must use

select( '#', ...)

On the other hand, the seemingly innocent idiom

local n = #...

doesn't do what I would expect when reading it, since the result you
get is in fact the length of the first value of '...', as in

local n = #(({...})[1])
or
local n = #(...)
or
local a = ...
local n = #a

Those two facts lead me to think that I'd rather have #... equal to
the number of elements found in '...', hence the attached patch
against Lua 5.2 alpha.
It does the trick, but as it is my first attempt at modifying the
parser, it is a bit clumsy, and I am not really happy with the way I
did it. More to the point, I don't like the virtual token TK_LENDOTS,
which is not actually generated by the lexer, but manually when the
lexer finds '#' followed by TK_DOTS. I'd be interested to see the
proper way to do it.

Also, I have tried, without success so far for lack of knowledge
regarding the VM itself, to further the job to allow for ...[exp], to
be able to index the vararg list without using select(). I think that
this would be possible by changing the OP_VARARG opcode to accept some
flag in C to tell it to interpret B as a register where to read the
index. My problem yet is the generate the bytecode that actually
evaluates the expression. I'd appreciate some help with this.


All in all, I'd be favorable for those two changes to be introduced in
Lua 5.2 for the following reasons:

current state:

#... is a faux-ami, much better understood as
local a = ...
local n = #a

I find rather awkward to be obliged to resort to a function call just
to be able to count the number of elements or to extract one such
element in a language construct when the VM has all the required
information.
It also breaks my heart when I think about all the stack adjustments
that go on under the hood just because of that function call :-).

I can't really think of a situation where one would call select('#'/n,
<X>) where <X> is not '...'. Because of this, select is a function
that looks to me like an imperfect solution to the real problem of
counting and indexing '...', posed by the fact that '...' is not a
first-class value, but an expression.

patched state:

#... does what I expect of it :-)

select( '#', ...) can be deprecated

select( n, ...) can still be useful for situations when one actually
needs to skip the n-1 first elements but retain all the others, but
...[n] is just easier to write and faster for the VM when one needs to
get only one element out of '...'.

local a = ...; local n = #a is still valid if you really want to know
the length of the first element of '...'.

One can iterate over the contents of '...' by only using the language
constructs, without having to generate an intermediate table or to use
function calls( be it ipairs or select).


I am aware that all this is rather minor, and that what I described is
nothing more than what I perceive as a perfected and more elegant way
of doing something that can already be achieved. But isn't Lua about
elegance and/or/through perfection, and vice-versa?


-- 
Benoit.

Attachment: lendots.patch
Description: Binary data