~technomancy/fennel#69: 
& rest destructuring does not work for proxy tables on Lua 5.2 and Luajit

The following code works on 5.3 and 5.4 as expected, but returns empty table on 5.2 and LuaJit:

(let [[_ & rest] (setmetatable [] {:__index [1 2 3] :__len (fn [] 3)}))]
  rest)

This is because unpack doesn't yet respect these two metamethods:

local function len()
  return 3
end
local _let_1_ = setmetatable({}, {__index = {1, 2, 3}, __len = len})
local _ = _let_1_[1]
local rest = {(table.unpack or unpack)(_let_1_, 2)}
return rest

Instead, Fennel compiler could generate a for loop:

  return 3
end
local _let_1_ = setmetatable({}, {__index = {1, 2, 3}, __len = len})
local _ = _let_1_[1]
local rest = {}
for i = 2, #_let_1_ do
  rest[(i - 1)] = _let_1_[i]
end
return nil

This has an additional advantage of supported tables of unlimited size, whereas unpack will only work on tables of size up to 8000 elements on LuaJit:

Welcome to Fennel 0.10.0-dev on Lua 5.1!
Use ,help to see available commands.
>> (let [t []
        _ (for [i 1 8000]
               (tset t i i))
        [x & xs] t]
        xs)
runtime error: too many results to unpack
stack traceback:
  [C]: in function 'unpack'
  [string "local t = {}..."]:9: in main chunk
  /home/andreyorst/.local/bin/fennel:479: in function ?
  [C]: in function 'xpcall'
  /home/andreyorst/.local/bin/fennel:484: in function 'repl'
  /home/andreyorst/.local/bin/fennel:4797: in function ?
  [C]: in ?
Status
REPORTED
Submitter
~andreyorst
Assigned to
No-one
Submitted
2 months ago
Updated
2 months ago
Labels
No labels applied.