for-loopluasyntaxlua-tablelua-4.0

Why does `for key, value in table` stop working in Lua 5.1 and later?


The source code for every Lua release is available in one handy package, which can be extracted and the versions can be compiled all at once:

wget https://www.lua.org/ftp/lua-all.tar.gz
tar xvf lua-all.tar.gz --strip-components=1
make

Afterwards, you can run example code in all versions to compare:

cat <<EOF >pairs.lua
for key, value in pairs({[2] = "a", [1] = "b", ["c"] = "d"}) do
    print(key .. " -> " .. value)
end
EOF
ls -1d */ | sed 's/\/$//' | sort | while IFS= read -r f; do printf %s\\n "" "$f"; "$f/lua" pairs.lua; done

Outputs:


lua-1.0
lua: syntax error near "key" at line 1 in file "pairs.lua"

lua-1.1
lua: syntax error near "key" at line 1 in file "pairs.lua"

lua-2.1
lua: syntax error near "key" at line 1 in file "pairs.lua"

lua-2.2
lua: syntax error near "key" at line 1 in file `pairs.lua'
Active Stack:
    fallback error

lua-2.4
lua: syntax error; last token read: "key" at line 1 in file `pairs.lua'
Active Stack:
    `error' fallback
lua: error trying to run file pairs.lua

lua-2.5
lua: syntax error;
> last token read: "key" at line 1 in file pairs.lua
Active Stack:
    `error' fallback

lua-2.5.1
lua: syntax error;
> last token read: "key" at line 1 in file pairs.lua
Active Stack:
    `error' fallback

lua-3.0
lua: syntax error;
> last token read: "key" at line 1 in file pairs.lua

lua-3.1
lua: `=' expected;
  last token read: `key' at line 1 in chunk `pairs.lua'

lua-3.2

lua-3.2.1
lua error: `=' expected;
  last token read: `key' at line 1 in file `pairs.lua'

lua-3.2.2
lua error: `=' expected;
  last token read: `key' at line 1 in file `pairs.lua'

lua-4.0
error: attempt to call global `pairs' (a nil value)
stack traceback:
   1:  main of file `pairs.lua' at line 1

lua-4.0.1
error: attempt to call global `pairs' (a nil value)
stack traceback:
   1:  main of file `pairs.lua' at line 1

lua-5.0
1 -> b
2 -> a
c -> d

lua-5.0.1
1 -> b
2 -> a
c -> d

lua-5.0.2
1 -> b
2 -> a
c -> d

lua-5.0.3
1 -> b
2 -> a
c -> d

lua-5.1
2 -> a
1 -> b
c -> d

lua-5.1.1
2 -> a
1 -> b
c -> d

lua-5.1.2
2 -> a
1 -> b
c -> d

lua-5.1.3
1 -> b
2 -> a
c -> d

lua-5.1.4
1 -> b
2 -> a
c -> d

lua-5.1.5
1 -> b
2 -> a
c -> d

lua-5.2.0
2 -> a
1 -> b
c -> d

lua-5.2.1
2 -> a
1 -> b
c -> d

lua-5.2.2
2 -> a
1 -> b
c -> d

lua-5.2.3
2 -> a
1 -> b
c -> d

lua-5.2.4
2 -> a
1 -> b
c -> d

lua-5.3.0
1 -> b
2 -> a
c -> d

lua-5.3.1
1 -> b
2 -> a
c -> d

lua-5.3.2
1 -> b
2 -> a
c -> d

lua-5.3.3
1 -> b
2 -> a
c -> d

lua-5.3.4
1 -> b
2 -> a
c -> d

lua-5.3.5
1 -> b
2 -> a
c -> d

lua-5.3.6
1 -> b
2 -> a
c -> d

lua-5.4.0
1 -> b
2 -> a
c -> d

lua-5.4.1
1 -> b
2 -> a
c -> d

lua-5.4.2
1 -> b
2 -> a
c -> d

lua-5.4.3
1 -> b
2 -> a
c -> d

lua-5.4.4
1 -> b
2 -> a
c -> d

lua-5.4.5
1 -> b
2 -> a
c -> d

lua-5.4.6
1 -> b
2 -> a
c -> d

lua-5.4.7
1 -> b
2 -> a
c -> d

And:

cat <<EOF >ipairs.lua
for key, value in ipairs({[2] = "a", [1] = "b", ["c"] = "d"}) do
    print(key .. " -> " .. value)
end
EOF
ls -1d */ | sed 's/\/$//' | sort | while IFS= read -r f; do printf %s\\n "" "$f"; "$f/lua" ipairs.lua; done

Outputs:


lua-1.0
lua: syntax error near "key" at line 1 in file "ipairs.lua"

lua-1.1
lua: syntax error near "key" at line 1 in file "ipairs.lua"

lua-2.1
lua: syntax error near "key" at line 1 in file "ipairs.lua"

lua-2.2
lua: syntax error near "key" at line 1 in file `ipairs.lua'
Active Stack:
    fallback error

lua-2.4
lua: syntax error; last token read: "key" at line 1 in file `ipairs.lua'
Active Stack:
    `error' fallback
lua: error trying to run file ipairs.lua

lua-2.5
lua: syntax error;
> last token read: "key" at line 1 in file ipairs.lua
Active Stack:
    `error' fallback

lua-2.5.1
lua: syntax error;
> last token read: "key" at line 1 in file ipairs.lua
Active Stack:
    `error' fallback

lua-3.0
lua: syntax error;
> last token read: "key" at line 1 in file ipairs.lua

lua-3.1
lua: `=' expected;
  last token read: `key' at line 1 in chunk `ipairs.lua'

lua-3.2

lua-3.2.1
lua error: `=' expected;
  last token read: `key' at line 1 in file `ipairs.lua'

lua-3.2.2
lua error: `=' expected;
  last token read: `key' at line 1 in file `ipairs.lua'

lua-4.0
error: attempt to call global `ipairs' (a nil value)
stack traceback:
   1:  main of file `ipairs.lua' at line 1

lua-4.0.1
error: attempt to call global `ipairs' (a nil value)
stack traceback:
   1:  main of file `ipairs.lua' at line 1

lua-5.0
1 -> b
2 -> a

lua-5.0.1
1 -> b
2 -> a

lua-5.0.2
1 -> b
2 -> a

lua-5.0.3
1 -> b
2 -> a

lua-5.1
1 -> b
2 -> a

lua-5.1.1
1 -> b
2 -> a

lua-5.1.2
1 -> b
2 -> a

lua-5.1.3
1 -> b
2 -> a

lua-5.1.4
1 -> b
2 -> a

lua-5.1.5
1 -> b
2 -> a

lua-5.2.0
1 -> b
2 -> a

lua-5.2.1
1 -> b
2 -> a

lua-5.2.2
1 -> b
2 -> a

lua-5.2.3
1 -> b
2 -> a

lua-5.2.4
1 -> b
2 -> a

lua-5.3.0
1 -> b
2 -> a

lua-5.3.1
1 -> b
2 -> a

lua-5.3.2
1 -> b
2 -> a

lua-5.3.3
1 -> b
2 -> a

lua-5.3.4
1 -> b
2 -> a

lua-5.3.5
1 -> b
2 -> a

lua-5.3.6
1 -> b
2 -> a

lua-5.4.0
1 -> b
2 -> a

lua-5.4.1
1 -> b
2 -> a

lua-5.4.2
1 -> b
2 -> a

lua-5.4.3
1 -> b
2 -> a

lua-5.4.4
1 -> b
2 -> a

lua-5.4.5
1 -> b
2 -> a

lua-5.4.6
1 -> b
2 -> a

lua-5.4.7
1 -> b
2 -> a

As expected, the code starts working with Lua 5.0, which is when pairs and ipairs was introduced.

My question is about the following example:

cat <<EOF >neither.lua
for key, value in {[2] = "a", [1] = "b", ["c"] = "d"} do
    print(key .. " -> " .. value)
end
EOF
ls -1d */ | sed 's/\/$//' | sort | while IFS= read -r f; do printf %s\\n "" "$f"; "$f/lua" neither.lua; done

Outputs:


lua-1.0
lua: syntax error near "key" at line 1 in file "neither.lua"

lua-1.1
lua: syntax error near "key" at line 1 in file "neither.lua"

lua-2.1
lua: syntax error near "key" at line 1 in file "neither.lua"

lua-2.2
lua: syntax error near "key" at line 1 in file `neither.lua'
Active Stack:
    fallback error

lua-2.4
lua: syntax error; last token read: "key" at line 1 in file `neither.lua'
Active Stack:
    `error' fallback
lua: error trying to run file neither.lua

lua-2.5
lua: syntax error;
> last token read: "key" at line 1 in file neither.lua
Active Stack:
    `error' fallback

lua-2.5.1
lua: syntax error;
> last token read: "key" at line 1 in file neither.lua
Active Stack:
    `error' fallback

lua-3.0
lua: syntax error;
> last token read: "key" at line 1 in file neither.lua

lua-3.1
lua: `=' expected;
  last token read: `key' at line 1 in chunk `neither.lua'

lua-3.2

lua-3.2.1
lua error: `=' expected;
  last token read: `key' at line 1 in file `neither.lua'

lua-3.2.2
lua error: `=' expected;
  last token read: `key' at line 1 in file `neither.lua'

lua-4.0
1 -> b
c -> d
2 -> a

lua-4.0.1
1 -> b
c -> d
2 -> a

lua-5.0
1 -> b
2 -> a
c -> d

lua-5.0.1
1 -> b
2 -> a
c -> d

lua-5.0.2
1 -> b
2 -> a
c -> d

lua-5.0.3
1 -> b
2 -> a
c -> d

lua-5.1
lua-5.1/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: ?

lua-5.1.1
lua-5.1.1/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: ?

lua-5.1.2
lua-5.1.2/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: ?

lua-5.1.3
lua-5.1.3/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: ?

lua-5.1.4
lua-5.1.4/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: ?

lua-5.1.5
lua-5.1.5/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: ?

lua-5.2.0
lua-5.2.0/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.2.1
lua-5.2.1/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.2.2
lua-5.2.2/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.2.3
lua-5.2.3/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.2.4
lua-5.2.4/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.3.0
lua-5.3.0/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.3.1
lua-5.3.1/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.3.2
lua-5.3.2/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.3.3
lua-5.3.3/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.3.4
lua-5.3.4/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.3.5
lua-5.3.5/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.3.6
lua-5.3.6/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.4.0
lua-5.4.0/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.4.1
lua-5.4.1/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.4.2
lua-5.4.2/lua: neither.lua:1: attempt to call a table value
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.4.3
lua-5.4.3/lua: neither.lua:1: for iterator 'for iterator' is not callable (a table value)
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.4.4
lua-5.4.4/lua: neither.lua:1: attempt to call a table value (for iterator 'for iterator')
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.4.5
lua-5.4.5/lua: neither.lua:1: attempt to call a table value (for iterator 'for iterator')
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.4.6
lua-5.4.6/lua: neither.lua:1: attempt to call a table value (for iterator 'for iterator')
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

lua-5.4.7
lua-5.4.7/lua: neither.lua:1: attempt to call a table value (for iterator 'for iterator')
stack traceback:
    neither.lua:1: in main chunk
    [C]: in ?

This for key, value in table syntax starts working with Lua 4.0, but stops working in Lua 5.1 and later. What is the reason for this? While it was working, was it equivalent to pairs?

There's already quite a few posts about generic for loops in Lua - like How to iterate through table in Lua?, What is the difference between pairs() and ipairs() in Lua?, Is there any way to loop through an array without using pairs()? or for in loop with key value pairs, to mention a few - but as far as I can tell, none of them contain an answer to this question.


Solution

  • Lua 5.0 introduced the more powerful generic for statement which works over functions and can be used to implement generic iterators. Lua 5.0 kept "for k,v in t" for compatibility but marked it deprecated. As such, it was removed in Lua 5.1. See the section "Incompatibilities with version 4.0" in the Lua 5.0 Reference Manual.

    In Lua 5.0+, you can use "for k,v in next,t", which is equivalent to "for k,v in pairs(t)".