lua-users home
lua-l archive

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


Patrick Donnelly <batrick@batbytes.com> wrote:
(24/06/2009 04:44)


>>    C:\WINDOWS\Desktop>lua
>>    Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
>>    > x={}
>>    > x[40]=5
>>    > print(#x)
>>    0
>>    > print(x[40])
>>    5
>>    > table.remove(x,40)
>>    > print(x[40])
>>    5
>>    >
>>
>> Is this intentional? I notice that with Lua v4, you can do it. x[40] will be nil.
>
>It is intentional. table.remove (like table.insert) expects an array
>for its table argument. It strictly checks that the value being
>removed is within the array's bounds (that is, 1 - #t).
>

Ok, thanks, so long as it's right and not going to change unexpectedly I can cope with it somehow.

>> Here are two different scripts for same purpose of syncing two arrays according to operations carried out on one of them:
>>
>>    X={0,0,0,0,0,1,1,1,1,2,2,3,4,5,5,5,5,5,6,6,6,6,6,6,6,6,7,8,8,8,8,8,8,8,8,8,9,9,9,9}
>>    Y={}
>>    for N=#X,1,-1 do
>>      Y[N]=N
>>      if X[N]==X[N+1] then  table.remove(X,N+1)  table.remove(Y,N+1)  end
>>    end
>>    print(unpack(X))
>>    print(unpack(Y))
>>
>>    X={0,0,0,0,0,1,1,1,1,2,2,3,4,5,5,5,5,5,6,6,6,6,6,6,6,6,7,8,8,8,8,8,8,8,8,8,9,9,9,9}
>>    Y={}
>>    for N=getn(X),1,-1 do
>>      Y[N]=N
>>      if X[N]==X[N+1] then  tremove(X,N+1)  tremove(Y,N+1)  end
>>    end
>>    for N=1,getn(X) do  print(X[N])  end
>>    for N=1,getn(Y) do  print(Y[N])  end
>>

[snip..]

>I would use this code to get your "sync" behavior above (If I
>understand the intent correctly):
>
>X={0,0,0,0,0,1,1,1,1,2,2,3,4,5,5,5,5,5,6,6,6,6,6,6,6,6,7,8,8,8,8,8,8,8,8,8,9,9,9,9}
>Y = {}
>for i, v in ipairs(X) do
>  Y[i] = v;
>  while X[i+1] == v do table.remove(X, i+1); end
>end
>

Nope. :) If it worked, the table Y would contain the ten indices at which the values in table X had changed, (as seen in an upward count). Also, the reason I work backward is to overcome the #t value being fetched at iterator start, not re-evaluated at each iteration. If I work backwards I know I won't eventually run into errors based on trying to operate on nil values as #t decreases. Also, the speed of traversing large tables increases as less elements have to be moved, as the bulk of removal is done well before I reach the top of the table. This lets me operate on data in place rather than via intermediate or temporary tables, which I find ugly. So even if there IS a way to do it forwards, it's likely not desirable. Would be nice if ipairs() could iterate backwards, but nothing wrong with a decrementing for loop...

>> PS. I notices 'setn' is deprecated. If I wanted to do it, can it be done some other way, and if so, how?
>
>When I have needed to set the length of a table manually, I have used
>key 'n' in the table. An example of how it can be used is gathering
>the return values of a function in a table:
>
>function pack (...)
>  return {n = select("#", ...), ...}
>end
>

That's a nice construct but weirdly, it's not necessary so long as n is copied from #t before anything else is done to that table. If you're providing every element, regardless of nil values present, the # is set to the number of arguments added anyway, and my table.remove(x,40) works. I just tested this.. If you just hand the arguments as comma-separated values inside T={x,y,x,nil,nil,1,2,3,...} you get a table with # equal to the number of values, and table.remove works on any element, as expected, at least it does the FIRST time, as then the # value changes to (first nil element)-1. Further, if you declare an empty table and populate it later, this secondary behaviour occurs at the outset because # remains 0 if the first value is nil. Two snippets to illustrate:

    x={nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil}  --39 nils
    x[40]=5
    print(#x)
    print(x[40])
    table.remove(x,10)
    print(x[40])
    print(x[39])
    print(#x)

    x={}
    for n=1,39 do  x[n]=nil  end
    x[40]=5
    print(#x)
    print(x[40])
    table.remove(x,10)
    print(x[40])
    print(x[39])
    print(#x)

To solve my case I do need to iterate backwards as I described earlier, but I might be ok because the initial table to which others must be synced is full of values and no holes so I can use its # value at any time, and if it weren't I could always do a for loop to fill an empty table with empty strings or 0's to make # work at all times, though this last 'fix' isn't the kind of neatness and power I've come to value in Lua. :)

Above all, I like that I can make an array in a table and populate negative indices with values with the positive indices, accessed by simple arithmetical sign to choose which of the pair to use, or add arbitrary key/value pairs without affecting the array (ipairs() function) behaviour. I find that extremely elegant and strong, and I hope that isn't going to change. It looks like I've found a quirk that might imply that something is going to change though..