lua-users home
lua-l archive

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

On 2-Sep-05, at 1:35 PM, William Trenker wrote:

On 9/1/05, Rici Lake <> wrote:

Let's trust the implementers to worry about
the low-level stuff, and get it right. We can just think about the
semantics, and how to write beautiful programs with that.

Agreeing wholeheartedly, may I pick a nit?  Aren't there some
high-level semantics that can be derailed when the programmer has no
option but to work too close to the details?  A simple example is
testing for an empty table.

Actually, this is a semantic question. What is the table? How is empty defined?

If the table is being used as a vector, and the vector is known to be dense (i.e. there are no internal nils), then the test is easy:

  if t[1] == nil then ...

This deliberately avoids testing for "emptiness", because I might be storing metadata in the table which does not affect emptiness. (For example, I might have chosen to set t.n to 0, in which case I could also check to see if t.n was 0 :)

If the table is a dictionary, then the standard way of testing would be next(t). I often put:

  local hasdata = next

at the top of my code to make that particular test more readable.

But in some applications, I might only care about certain table keys and not other ones. In other applications, the table might be non-empty even if it has no direct data, because it has been indirected with an __index metamethod to another table. So in those cases, I would have to construct my own appropriate test for emptiness.

These different mechanisms are not competing on efficiency. They are competing on semantic correctness. In general, with a few exceptions, you'll find that the least contrived way of doing something is the fastest, in any scripting language, because the cost of interpretation (even VM interpretation) plus the cost of function calls (or the "C/scripting frontier", if you prefer) tends to outweigh other considerations.

Once you have a working program, you can certainly start thinking about efficiency. But even there, I would say your first steps are:

1) use a good algorithm
2) use data structures and control flow structures which co-operate well with Lua.

(By the way, the fastest test for empty on a dense vector is the t[1] = nil test, but if you're tracking the vector size anyway, t.n == 0 is slightly faster. However, it's not worth tracking vector size just for the sake of that test; you would only do it if the vector was sparse in which case table.getn doesn't give you reliable results, at least in 5.1)