lua-users home
lua-l archive

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


not to detract anyone from the current syntactic flamewar,
but there's another problem with *s (where s is a string):

$ time lua51w6 -e 'local s=""; for i=1,1e7 do local x = *s end'
$ time lua51w6 -e 'local s=""; for i=1,1e7 do local x = s:len() end' 
$ time lua51w6 -e 'local s,f="",string.len; for i=1,1e7 do local x = f(s) end'

[Lower numbers are better]

Well, looks like string.len is faster (!) than *s. This is
because the current implementation needs to go through the
string metatable every time. Patch attached below.

Look at the improvement:

$ time lua51w6-slen -e 'local s=""; for i=1,1e7 do local x = *s end'

The semantic difference is that you cannot swap string.* and
expect *s to get a new meaning for plain strings. But the only
reason you'd want to do that would be for UTF-8. And there
every string has both a 'length' and a 'size'. Since this is
a matter of definition only, you ought to use s:len() consistently
when you want the length in characters and use *s when you want
the storage size.

Oh and another thing: did anyone notice that *t is _NOT_
overridable for plain tables? That makes it much less useful.
You cannot construct your own types with plain tables and
give *t any other meaning (you can do so with userdata).

Alas, the performance of *t for large tables isn't stellar
(it needs to do a binary search). So making it check the
metatable everytime would slow it down even more ...

So, returning you to the syntactic flamewar: I want to
voice my opinion that ...

  t[*t+1] = x
... looks really, really ugly for an append operation.

Read the old thread for a bunch of suggestions. I'd rather
have an append operator (t[] = x) than a size/length operator.
The former is much more useful in a high-level language since
'size' is a low-level property of objects and should be
encapsulated by high-level methods (e.g. iterators).


--- lua-5.1-work6/src/lvm.c
+++ lua-5.1-work6-slen/src/lvm.c
@@ -549,6 +549,9 @@
         if (ttype(rb) == LUA_TTABLE) {
           setnvalue(ra, cast(lua_Number, luaH_getn(hvalue(rb))));
+        else if (ttype(rb) == LUA_TSTRING) {
+          setnvalue(ra, cast(lua_Number, tsvalue(rb)->len));
+        }
         else {  /* try metamethod */
             if (!call_binTM(L, rb, &luaO_nilobject, ra, TM_SIZ))