Concatenation of strings in Lua

John Mark Mitchell picture John Mark Mitchell · Sep 10, 2009 · Viewed 114.9k times · Source

In many languages you can concatenate strings on variable assignment. I have a scenario, using the Lua programming language, where I need to append the output of a command to an existing variable. Is there a functional equivalent in Lua to the below examples?

Examples of other languages:

===== PERL =====
$filename = "checkbook";
$filename .= ".tmp";
================

===== C# =====
string filename = "checkbook";
filename += ".tmp";
===============

Thank you in advance for your help.

Answer

RBerteig picture RBerteig · Sep 10, 2009

As other answers have said, the string concatenation operator in Lua is two dots.

Your simple example would be written like this:

filename = "checkbook"
filename = filename .. ".tmp"

However, there is a caveat to be aware of. Since strings in Lua are immutable, each concatenation creates a new string object and copies the data from the source strings to it. That makes successive concatenations to a single string have very poor performance.

The Lua idiom for this case is something like this:

function listvalues(s)
    local t = { }
    for k,v in ipairs(s) do
        t[#t+1] = tostring(v)
    end
    return table.concat(t,"\n")
end

By collecting the strings to be concatenated in an array t, the standard library routine table.concat can be used to concatenate them all up (along with a separator string between each pair) without unnecessary string copying.

Update: I just noticed that I originally wrote the code snippet above using pairs() instead of ipairs().

As originally written, the function listvalues() would indeed produce every value from the table passed in, but not in a stable or predictable order. On the other hand, it would include values who's keys were not positive integers in the span of 1 to #s. That is what pairs() does: it produces every single (key,value) pair stored in the table.

In most cases where you would be using something like listvaluas() you would be interested in preserving their order. So a call written as listvalues{13, 42, 17, 4} would produce a string containing those value in that order. However, pairs() won't do that, it will itemize them in some order that depends on the underlying implementation of the table data structure. It is known that the order not only depends on the keys, but also on the order in which the keys were inserted and other keys removed.

Of course ipairs() isn't a perfect answer either. It only enumerates those values of the table that form a "sequence". That is, those values who's keys form an unbroken block spanning from 1 to some upper bound, which is (usually) also the value returned by the # operator. (In many cases, the function ipairs() itself is better replaced by a simpler for loop that just counts from 1 to #s. This is the recommended practice in Lua 5.2 and in LuaJIT where the simpler for loop can be more efficiently implemented than the ipairs() iterator.)

If pairs() really is the right approach, then it is usually the case that you want to print both the key and the value. This reduces the concerns about order by making the data self-describing. Of course, since any Lua type (except nil and the floating point NaN) can be used as a key (and NaN can also be stored as a value) finding a string representation is left as an exercise for the student. And don't forget about trees and more complex structures of tables.