lua-users home
lua-l archive

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


Milano Carvalho escribió:

> I don't know why the table constructor, in Lua 5, doesn't set the total
> number of elements when there is a nil value among them.

The table constructor didn't set the number of elements in Lua 4 either.
But that is not the issue. The issue is that table.foreachi() doesn't use
the information. It simply stops at the first nil element. (This is
contrary to the documentation -- I don't know if the implementation or the
documentation is incorrect.)

If you want to iterate a sparse array with numeric indices, try this:

for i = 1, table.getn(t) do
  local v = t[i]
  -- whatever
end

You could package this up into a function if you wanted to:

-- foreachi with documented behaviour:
function foreachi(t, fn)
  local n = table.getn(t)
  for i = 1, n do
    local rv = fn(i, t[i])
    if rv then return rv end
  end
end

--

On a related issue, getn can sometimes have to go to a lot of trouble to
figure out what the table size is. It is generally better to set it
yourself, and then make sure that it is maintained. The simplest way to get
it set correctly in the first place is to use the following:

   function Vector(...) return arg end

This relies on the behaviour of the arg pseudo-parameter, which has the "n"
field set correctly.

--

On another related issue, a question was posed on automatically setting
"n", with a suggested pseudo-patch. (I don't have those handy because the
mailsystem I use failed this weekend, so I saw them on yahoo.) My
suggestion is that if you want that behaviour, you use a __newindex
metamethod. Continuing the above example:

  do
    local meta = {}
    function meta:__newindex(i, v)
      if type(i) == "number" and i > table.getn(self) then
        table.setn(self, i)
      end
      rawset(self, i, v)
    end

    function Vector(...)
      return setmetatable(arg, meta)
    end
  end

This will not slow down table.insert() because it does a rawset (and
updates the table size itself). It basically protects you from the case
where you set table values directly without using the table API, and in
that case it only slows things down if you're setting a table index for the
first time.

The pseudo-patch suggested by (was it David Holz?) is more difficult to
write in Lua5beta than it looks because the "n" value is internal to the
table package. However, it has been announced that it will be made
available to the C API in Lua5 release. Even so, I don't think it is a good
idea to do this on all tables: I might have good reasons for *not* updating
the table size in some applications (for example, I might want to assign
table keys which will not be iterated during a foreachi-type iteration --
the foreachi above, not the foreachi as implemented in Lua5beta.) Magically
changing the table size would make this impossible. Furthermore, if I am
not using the table API on some table and that table has an "n" key, I may
not want the "n" key to magically change its value as the result of
assigning a numeric key in that table.

Lua allows me to provide specific behaviour to specific types of tables,
and I think that is a good thing.

Hope that helps,
Rici.