lua-users home
lua-l archive

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


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

>             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?]