Associativity Of Concatenation |
|
..
(concatenation) and ^
(exponentiation). Having ^
be right associative is not unusual for languages, but it is somewhat unusual for ..
to be right associative. For most cases, it doesn't matter whether ..
is evaluated with right or left associativity because string concatenation is associative, but if the objects being concatenated have metamethods or if a large number of objects are being concatenated (e.g. 199 or more -- the precise limit is determined by LUAI_MAXCCALLS
in luaconf.h), then the effect can be noticeable. The reason for ..
being right-associative rather than the usual left-associative for Lua operators seems mainly to do with efficiency of implementation (see LuaList:2002-08/msg00218.html and LuaList:2002-08/msg00104.html).
The problem of concatenating more than approximately 199 elements at a time is shown below. This Lua program creates a Lua program that does not compile:
print([[return 0]] .. ([[ .. 0]]):rep(198))
lua test.lua | luac -p -l - luac: stdin:1: chunk has too many syntax levels
If we reduce the 198 to 10, we can see why:
main <stdin:0,0> (14 instructions, 56 bytes at 0x671200) 0+ params, 11 slots, 0 upvalues, 0 locals, 1 constant, 0 functions 1 [1] LOADK 0 -1 ; "" 2 [1] LOADK 1 -1 ; "" 3 [1] LOADK 2 -1 ; "" 4 [1] LOADK 3 -1 ; "" 5 [1] LOADK 4 -1 ; "" 6 [1] LOADK 5 -1 ; "" 7 [1] LOADK 6 -1 ; "" 8 [1] LOADK 7 -1 ; "" 9 [1] LOADK 8 -1 ; "" 10 [1] LOADK 9 -1 ; "" 11 [1] LOADK 10 -1 ; "" 12 [1] CONCAT 0 0 10 13 [1] RETURN 0 2 14 [1] RETURN 0 1
The compiler causes all the constants to be placed on the stack prior to the concatenation. The same error occurs when the operator is ^
, though the need for exponentiating approximately 200 objects is probably quite rare, unless maybe if ^
is overridden with different semantics (which might not be a good idea anyway).
Now if a left-associative operator is used (e.g. addition), then this type of code compiles fine:
print([[return a]] .. ([[ + a]]):rep(198))
main <stdin:0,0> (399 instructions, 1596 bytes at 0x671200) 0+ params, 2 slots, 0 upvalues, 0 locals, 1 constant, 0 functions 1 [1] GETGLOBAL 0 -1 ; a 2 [1] GETGLOBAL 1 -1 ; a 3 [1] ADD 0 0 1 4 [1] GETGLOBAL 1 -1 ; a 5 [1] ADD 0 0 1 6 [1] GETGLOBAL 1 -1 ; a 7 [1] ADD 0 0 1 ... 390 [1] GETGLOBAL 1 -1 ; a 391 [1] ADD 0 0 1 392 [1] GETGLOBAL 1 -1 ; a 393 [1] ADD 0 0 1 394 [1] GETGLOBAL 1 -1 ; a 395 [1] ADD 0 0 1 396 [1] GETGLOBAL 1 -1 ; a 397 [1] ADD 0 0 1 398 [1] RETURN 0 2 399 [1] RETURN 0 1
The objects are being pushed on the stack and operated on "[just in time]".
__concat
metamethod for some object. If your implementation of ..
is truly a concatenation operation, then it will also be associative, but the chained concatenation is broken down into pairwise calls to the __concat
metamethod, so your implementation will be called from right-to-left. One case where concatenation is not associative and is naturally right-binding is Posix regular expression concatenation; the first-longest match rule assumes that match components are concatenated right to left. I don't know if that's an answer: the real reason is probably that it's more efficient to implement in a stack machine. --RiciLake
^
for cross product, but associativities differ
..
for applying function decorators because of ..
's right-associativity.