lua-users home
lua-l archive

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


On Sat, Jan 08, 2011 at 09:21:05AM +0200, Henning Diedrich wrote:
> 
> Just to get it straight: can it ever make sense to insert nil using
> table.insert()?
> 
> 'Should' that not rather throw an error, because any table.insert() after
> that could have undefined behavior?
> 
> Isn't it pretty much guaranteed you'd never want to do
> |table.insert(t,n,nil)|?
> 
> Or is the rationale that you could fill that hole the next second and duly
> have a strict array again?
> 
> I tried writing a test loop with inserts and removes on associative arrays
> and could not come up with a prediction for insert (I understood, that's not
> defined). Insert replaces values in associative arrays sometimes, instead of
> moving values up as far as I can see. I can accept it just should not be
> used.
> 
> But why would insert be allowed to make the table invalid 'for itself' and
> put it in such a state. After all, it's not allowed to accept a string
> either. So why a nil? That's not a rhethoric question, I am wondering and if
> I have overlooked the decisive message in the list, let me know,
> 
We have had many discussions on this list on table functions,
and I think the following points are not in dispute:

1. The insert, remove and sort functions (and in Lua 5.2, the length
    operator) are designed to work for what I call annotated lists, 
    i.e. tables that may or may not contain non-numeric keys, but the 
    positive integer keys form a block from 1 to n, where n is the 
    length of the table.  
2. They give predictable and intuitively acceptable results when used
    in the situation for which they were designed.
3. They do not check whether the table has the required property and
    do not return an error message when used outside their design 
    specification.
4. Their behaviour in such cases, i.e. when used with a table with 
    holes, or when insert is called with "nil" as the element to be 
    inserted, is not defined, but can for a particular Lua version
    be deduced by making a few experiments.
5. Exception: although the behaviour of the length operator is
    undefined for a table with holes, a property that even in that
    case it must have, has been written into the reference manual.
6. insert(a,b) does not do the same as insert(a,b,nil).  This 
    behaviour would not be possible for a function of three arguments
    written in Lua itself.

In view of point 6, Steve Donovan has made the suggestion (also
not disputed) that it is good programming practice to define 'append'
to mean the same as 'insert', and to use 'append' only in the case
of two arguments, and 'insert' only in the case of three arguments.

The points highly in dispute all concern what the behaviour under 
point 4 should be.  Roberto and Luiz seem to be unimpressed by these 
discussions, so it is merely an intellectual game among those of 
us who take part (and actually, if your post did not start "Hi Dirk",
I would not have considered myself to be still among them).

To answer your questions, both answers IMHO, and sure to stir up 
the controversy yet again:

1. I agree with you: it never makes sense to insert nil.
    The fact that the current implementation allows you to make a hole 
    that way is a regrettable undocumented feature, caused by a design 
    flaw in the API.  
    It would have been less confusing if the three-argument insert  
    had the value before the key, so that insert(a,b,nil) means 
    insert(a,b) as it would have done if written in pure Lua.  In that 
    case it would quite obviously be impossible to insert nil.  
    But it is too late now.
2. It is easy to make a version that does that if you use append the
    way Steve suggests.
        local oldinsert = table.insert
        function table.append(a,b) oldinsert(a,b) end
        function table.insert(a,b,c) if c==nil -- etc
    No need to change Lua.

Dirk