6

I have two strings. One of them is often (but not always) empty. The other is huge:

a = ""
b = "... huge string ..."

I need to concatenate the two strings. So I do the following:

return a .. b

But, if a is empty, this would, temporarily, unnecessarily create a copy of the huge string.

So I thought to write it as follows:

return (a == "" and b) or (a .. b)

This would solve the problem. But, I was wondering: does Lua optimize a concatenation that involves an empty string? That is, if we write a .. b, does Lua check to see if either of the strings is empty and return the other one immediately? If so, I could simply write a ..b instead of the more elaborate code.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Niccolo M.
  • 3,363
  • 2
  • 22
  • 39
  • This might be of use: http://stackoverflow.com/questions/19138974/does-lua-optimize-the-operator – filmor Apr 01 '14 at 09:02
  • @filmor: It was I myself who asked that other question, which is not related to this one: that other question talks about folding `((a .. b) .. c) .. d` into `..(a,b,c,d)`. *This* question deals with something entirely else. – Niccolo M. Apr 01 '14 at 09:04
  • @Leri: I don't see how inspecting the bytecodes could help me answer the question: the string is either empty or not *at run time*, not at compile time. The code I wrote above, `a = ""`, is just to explain matters. It'd be `a = ...some expression... ` in real life. – Niccolo M. Apr 01 '14 at 09:10
  • Sorry, didn't see that. But in this question you have already been pointed to the source code of the relevant function. – filmor Apr 01 '14 at 10:20
  • @filmor: Yeah, I knew how I could figure out the answer to my own question, but I wanted to hear the perspective of experienced/wise users here. I almost always learn new things by reading answers to questions I already, or think I already, know. – Niccolo M. Apr 01 '14 at 11:03

1 Answers1

6

Yes, it does.

In the Lua 5.2 source code luaV_concat:

if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
  if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
    luaG_concaterror(L, top-2, top-1);
}
else if (tsvalue(top-1)->len == 0)  /* second operand is empty? */
  (void)tostring(L, top - 2);  /* result is first operand */
else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
  setobjs2s(L, top - 2, top - 1);  /* result is second op. */
}
else {
  /* at least two non-empty string values; get as many as possible */

The two else if parts are exactly doing the job of optimizing string concatenation when one of the operand is an empty string.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • 1
    Thanks for pointing me in the right direction. I see that Lua 5.1 (which I target) [doesn't do this optimization](http://www.lua.org/source/5.1/lvm.c.html#luaV_concat). LuaJIT seems to be [even worse](https://github.com/LuaDist/luajit/blob/master/src/lj_api.c#L704). So I'll have to do this optimization myself. (Please correct me if I'm wrong.) – Niccolo M. Apr 01 '14 at 09:30
  • @NiccoloM. That's interesting, didn't know the difference. There seems to be a check for zero length in both Lua 5.1 and LuaJIT source at first glance, but I didn't get into detail, I'll remember to update the answer when I'm sure what they do. – Yu Hao Apr 01 '14 at 14:41
  • @NiccoloM. Keep in mind that a) that's not the official LuaJIT repo and b) LuaJIT's concat operator probably doesn't use `lua_concat` internally, but rather its own internal API. – Colonel Thirty Two Apr 01 '14 at 15:08
  • @Yu Hao: Oh, I now see the zero check in 5.1, but I don't know what exactly it does. I'd greatly appreciate it if you update your answer when you find the time to investigate this. – Niccolo M. Apr 02 '14 at 09:58
  • @Colonel Thirty Two: I agree that my comment was naive; I did wrote "seems to"; I wish somebody who knows luaJIT better could chime in. – Niccolo M. Apr 02 '14 at 09:58