lua-users home
lua-l archive

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


Am 02.10.2013 23:35 schröbte Tim Hill:

The sum was purely an example to illustrate the difficulty in
creating a robust API. The issue here is the behavior of # when
arrays have holes are can thus be viewed either as a "array with
holes" or a "array with other integer keys after the end of the
array". # gives odd results in these cases, which means (to my mind)
its risky to use # when an array is not well-formed.

Yes, it is, so don't use it. There is a Lua API that provides stricter guarantees than `#`: `ipairs()`. You will always get a proper sequence and the problem of holes just vanishes, and what remains is the problem of determining if the table has the expected number of elements. If you write life-or-death software, you probably want to validate each array element anyway, the number of elements in the array is a small problem compared to that.

So: If you have an expected number of elements (`n`) use a numeric for loop from 1 to n, and the matter of holes in the array just disappears during type checking. If you don't have an exact expected number of elements, use `ipairs()` for type checking and do the number-of-elements check at the end. You can transform case 2 into case 1 by letting your API-users specify the number of elements *they* think the array should have as an extra parameter. After type-checking you should always keep track of the array-length using a variable or a table-field.


And thus I find it desirable to check to see if an array is well-formed before using # .. but there is no way to do this in Lua that is not O(n).

If this were all my code base, then, as others have suggested, the solution is "make sure you don't create ill-formed arrays", but it's NOT all my code base and I need to be defensive when writing APIs to be consumed by others.

--Tim


Philipp


TL;DR: I see no point in checking the sequence status of a table without checking that it doesn't contain arbitrary booleans/threads/strings/tables/userdata, etc. The later also requires O(n), and the usable sequence length then comes for free.