Caution
You want to be careful with a problem like this. Strings in Lua are incredibly fast -- but not without sacrificing memory. Lua actually caches every unique string while the program is running (this is where the speed benefit comes from), therefore every new concatenation of a string is held in memory. For example, a .. b
and b .. a
would be considered two unique strings and they would both be cached (assuming that a ~= b
).
This is because strings are treated as objects in Lua. If you create the same string twice, for example, letter = "A"
and char = "A"
, both variables just become references to "A" in memory.
This is also why you can't change strings in Lua. Once you create a string, that's it! Set in stone. You can only create new strings that are modified versions of other strings.
Why is This Important?
Usually this isn't an issue, and you shouldn't have to worry about this. However, in circumstances where this concatenation is occurring in a tight or continuous loop, this is crucial to know. Due to the fact that Lua is caching every new unique string that's created, your program will eventually start to throttle if this is not accounted for.
Imagine a scenario where your program is generating 10000 unique string codes:
This means your program is allocating memory for each one of those string objects. Yikes.
Solution I
A popular solution is to store the individual characters in a temporary table, then join them together with table.concat
-- this will avoid caching the string in Lua. Here's an example:
1 | local function randString(len) |
4 | chars [ i ] = string.char(math.random( 33 , 126 )) |
6 | return table.concat(chars) |
Now, depending on your desired outcome, you may require a different version of this solution. This function will take an integer (the length of the randomly generated string) and return a string with random characters that is length long.
The randomness of the string comes from picking a number between 33 and 126 (ASCII codes) and converting that code into a character by using string.char
Solution II
On the other hand, you may want to define a character set to pick random characters from instead of choosing between all the characters from 33-126. In this case, you could just pass an array and apply the same logic:
01 | local function randString(len, charSet) |
04 | chars [ i ] = charSet [ math.random(#charSet) ] |
06 | return table.concat(chars) |
09 | local charSet = { "a" , "b" , "c" , "!" } |
10 | print (randString( 5 , charSet)) |
It's your preference. You could also create some hybrid of the two by returning random characters from 33-126 if no character set is given, or choose characters in a defined set when one is given. I'll leave that for you to do if you're interested (or you could post another question about it if you want some help!)
Just a tip...
For the second solution, I would recommend defining your character set early on in your code instead of passing a new table with the same characters every single time. For example...
01 | local charSet = { "a" , "b" , "c" , "!" } |
07 | local function randString(len, charSet) |
10 | chars [ i ] = charSet [ math.random(#charSet) ] |
12 | return table.concat(chars) |
16 | print (randString( 5 , charSet)) |
17 | print (randString( 5 , charSet)) |
18 | print (randString( 5 , charSet)) |
19 | print (randString( 5 , charSet)) |
Let me know if you have any questions!