[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua 5.1+ and variable-argument tables
- From: Rici Lake <lua@...>
- Date: Fri, 20 Aug 2004 11:31:07 -0500
On 20-Aug-04, at 9:25 AM, Roberto Ierusalimschy wrote:
In my view, tuples are a *big* change to the language, no matter the
size of its implementation (which is "an implementation detail", after
all).
I personally have no problem with discussing implementation details :)
But let me be clear: the tuple proposal I made does not introduce a new
datatype. The datatype already exists: tuples are simply a function
closure.
The proposed syntactic changes simply allow a conventient way to create
them. So I don't see it as a major change.
The ... syntax, on the other hand, creates an odd sort of
pseudo-datatype
which is not a first-class object at all, but seems to require various
methods: count number of elements, slice (or some such), perhaps
iterate, etc.
My intuitive objection to ... is that it is not a first-class object,
and
so it seems to me inelegant. It doesn't really make the language more
expressive, so as far as I can see it's only point is to make one
particular
operation more efficient. Since tuples-as-functions do a reasonable job
of
optimising that particular operation, I see them as a plausible
alternative
which has the advantage of not introducing a new concept into the
language.
That change would add lots of complexity to the language, at least
"hidden" complexity. As soon as we decided to add tuples to Lua, lots
of
other decisions would follow, with lots of discussions for each of
those
decisions.
Adding tuples as an official datatype, different from function closures,
would raise these issues. I think immutable tuples with
equality-by-value
comparison would be a useful addition to the language, and I think some
discussion on this might be helpful. But I am not proposing it at this
time. Nonetheless, let me try to answer some of the questions.
Among others (without much thinking): are tuples immutable?
Mutable collections already exist in the form of tables. So the only
reason
to introduce a new datatype would be to take advantage of immutability.
Immutable vectors already exist in the language, but are restricted to
vectors of octets; in that sense, an immutable tuple could be seen as
a generalisation of (a different) existing datatype.
if so, how should be the semantics of tupple equality?
Immutable objects should be compared by value, I believe. This would be
a key advantage of immutable tuples. For example, it would allow their
use
as table keys. Currently, the only way to use a complex object as a
table
key (in this sense) is to serialise it into a character string, which is
quite awkward. As an example, implementing the LALR construction
algorithm
requires tables whose keys are essentially pairs of <state, item>.
Do tuples have metatables? Why not?
Do functions have metatables? No. Why not? I don't know. Should they?
Well, it would be useful from time to time, but I don't know that it is
a big deal. It would be nice to have some way to define binary
operators on
functions (compose, for example), but I've lived without it so far.
It might be nice to be able to __index or even __newindex a function,
but
you can (almost) always wrap it into a table to do that.
Should we have a "foreach" function for tuples? A "pair" iterator?
If there is some way of getting the length of the tuple, these are
very easy to write in Lua. A new tuple datatype would probably have some
primitive or library function which returned its length; but the
tuple-as-function implementation relies on the tuple function; one
possibility
would be the following tuple-function:
tuple() -- returns all values
tuple(j[, k]) -- returns the slice starting with j (default 1) and
and continuing to k (default end)
tuple(true) -- special case, returns length of tuple. (Could be
tuple(0))
Then the implementations of tuple.foreach and tuple.ipairs are quite
straight-forward.
However, I don't actually like "returns the length of the tuple". A
better
interface, imho, would be one which tells you whether the tuple was at
least
a particular length. Just a matter of taste, though.
Weak tuples?
If tuples are immutable, weak tuples are semantically questionable. Two
tuples
might suddenly become equal-by-value because different object members
became
unreachable and were turned into nil. Again, tables provide this
functionality.
Each of these subjects (and many many
others) would eventually emerge in the list; several times, probably.
Debate is good, no?
If the argument about efficiency is valid (the one about three
allocations versus one), I don't see why we cannot simply implement
tables more efficiently for those particular uses. First, as long as we
do not use a ".n" field, we are down to two allocations. (Would that
simple change give a 1/3 speedup?) Second, we could allocate tables
with
a variable tail where it would keep its original array part (the one
specified in its constructor, if smaller than some [small] limit). That
would be enough to use only one block for those tables. (The main
point
here is: how frequently we add new integer indices to tables created
with list constructors?)
All very true. I think tables could be optimised even more... but of
course
it is possible that such optimisations would be counterproductive in
other
cases.
About the "... hack", I do not see it as a hack at all (but of course
this is a matter of taste). It is a local change to the language, and
it
solves at least two problems: it allows an easy way to pass parameters
to main chunks and it eliminates the magic name "arg" (or is it "args"?
I can't remember ;).
Indeed, it is a matter of taste. And of course it is your taste which is
most important.
I don't see passing parameters to main chunks being particular
difficult now;
the only issue is that it is a trifle inefficient. And personally, I
would
prefer a syntax which allows for named varargs, which is why I proposed:
function foo(a, b, [rest])
Of course, if rest were going to be a
vararg-table-as-currently-implemented,
that should be:
function foo(a, b, {rest})
Extending that to assignment statements is a very small step (and
actually
quite easy to implement in 5.0.2, at least.)