lua-users home
lua-l archive

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


Hi,

Dmitriy Iassenev wrote:
> we use floats in Lua, but there is a problem, which, probably, is
> because of this change (we still use Lua 5.02). When iterating via a
> table, which indices are numbers, runtime error occured:
> 
> "invalid key for 'next'"

There are issues with floats, but table iteration should not be
one of them (unless your arrays have more than 2^24 elements).

The most common cause for this message is using lua_tostring() or
lua_tonumber() on the key inside the iteration loop. This call
may convert the key to the other type which in turn breaks the
iteration. One needs to copy the key with lua_pushvalue() before
using either call (it doesn't matter for the value).

The other common cause is modifying the table during traversal.
Only replacing existing keys with new values (including nil) is
allowed.

>             if (lua_isnumber(state,-2)) {
>                 lua_Number      next = lua_tonumber(state,-2);

Ouch! lua_isnumber() returns true for numbers _and_ strings which
can be converted to numbers. In fact it does a temporary
conversion, but doesn't store the resulting number. And then
lua_tonumber() has to repeat the (expensive) conversion. I'm
pretty sure you don't want to do this during a table traversal.
It may break the traversal, too (see above).

Avoid lua_isnumber() wherever possible, unless you really want
the auto-coercion. And even then you may want to use
lua_tonumber() directly and only add a lua_isnumber() check if
zero is returned. This is e.g. what luaL_checknumber() does.

You usually want to use this:
  if (lua_type(L, -2) == LUA_TNUMBER) ...
Or this:
  switch (lua_type(L, -2)) { case LUA_TNUMBER: ... case LUA_Txx: ... }


[BTW: Whatever Lua 5.2 or 6.0 may look like, but may I suggest
redesigning or at least renaming the auto-coercive API calls?]

Bye,
     Mike