2016-08-15 5 views
4

Я изучаю Lua для университетского класса в области разработки мобильных приложений, и в последнее время мы рассмотрели оператор многоточия (...), позволяющий использовать динамическое количество аргументов. Из любопытства я решил попробовать и выяснить, есть ли предел, сколько аргументов он может справиться, как выясняется это 248.Экспрессия Lua Ellipsis ограничена 248

Например:

function pr(...) 
    print(...) 
end 

pr(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1) 

Я думал, может быть, это зависит от ОС или связано с размером стека, поэтому я тестировал это как на Linux, так и на Windows, как на 32-битной, так и на 64-битной версиях каждого. Количество разрешенных элементов оставалось на уровне 248. Казалось бы, это жестко закодированный лимит. Если я пытаюсь> 248, то я получаю ошибку я получаю:

main.lua:30 function or expression too complex near <eof> 

Я не могу себе представить, кто нуждается в более чем 248 выражений в большинстве случаев, но и для тех случаев, есть способ обойти это? Кроме того, почему это 248? Это число не кажется особенным.

+0

Это будет зависеть от конкретной версии Lua, которую вы используете. Знаете ли вы, что Corona использует 5.1 или 5.2? – hugomg

+0

Corona использует lua 5.1, хотя я не тестировал это корона на linux. Я использовал терминал для запуска кода lua, и это использовало lua 5.3, поскольку я не мог заставить корону работать правильно. – Rhexis

ответ

6

Предел кадра стека

Ограничения вы приезжаете в не непосредственно о максимальном количестве функциональных параметров допускаются. Его максимальный размер фрейма стека Lua.

Следующий пример демонстрирует это. Локальные переменные в Lua также использовать слоты в кадре стека функции во и объявляя 200 локальных переменных мы теперь нужно только 48 параметров в функции печати для достижения предела:

local x001,x002,x003,x004,x005,x006,x007,x008,x009,x010 
local x011,x012,x013,x014,x015,x016,x017,x018,x019,x020 
local x021,x022,x023,x024,x025,x026,x027,x028,x029,x030 
local x031,x032,x033,x034,x035,x036,x037,x038,x039,x040 
local x041,x042,x043,x044,x045,x046,x047,x048,x049,x050 
local x051,x052,x053,x054,x055,x056,x057,x058,x059,x060 
local x061,x062,x063,x064,x065,x066,x067,x068,x069,x070 
local x071,x072,x073,x074,x075,x076,x077,x078,x079,x080 
local x081,x082,x083,x084,x085,x086,x087,x088,x089,x090 
local x091,x092,x093,x094,x095,x096,x097,x098,x099,x100 
local x101,x102,x103,x104,x105,x106,x107,x108,x109,x110 
local x111,x112,x113,x114,x115,x116,x117,x118,x119,x120 
local x121,x122,x123,x124,x125,x126,x127,x128,x129,x130 
local x131,x132,x133,x134,x135,x136,x137,x138,x139,x140 
local x141,x142,x143,x144,x145,x146,x147,x148,x149,x150 
local x151,x152,x153,x154,x155,x156,x157,x158,x159,x160 
local x161,x162,x163,x164,x165,x166,x167,x168,x169,x170 
local x171,x172,x173,x174,x175,x176,x177,x178,x179,x180 
local x181,x182,x183,x184,x185,x186,x187,x188,x189,x190 
local x191,x192,x193,x194,x195,x196,x197,x198,x199,x200 
print(
1,1,1,1,1,1,1,1,1,1, 
1,1,1,1,1,1,1,1,1,1, 
1,1,1,1,1,1,1,1,1,1, 
1,1,1,1,1,1,1,1,1,1, 
1,1,1,1,1,1,1,1 
) 

Это также объясняет, почему ошибка сообщение читает function or expression too complex вместо too many arguments passed to function или что-то в этом роде.

Почему 248?

Максимальный размер кадра стека на самом деле 249. В llimits.h, Луа определяет MAXSTACK до 250, а в lcode.c, функция checkstack допускает только stackframes, которые меньше, чем ..

if (newstack >= MAXSTACK) 
     luaX_syntaxerror(fs->ls, "function or expression too complex"); 

Это соответствует результатам, которые мы получаем в наших экспериментах. Байт-код для вызова функции f(a1,a2,...,an) потребует регистров N+1 в стеке: один указывает на функцию, которую мы вызываем, и N указывает на аргументы функции и 248 + 1 = 249 < = 250. (Нам также понадобится дополнительные регистры при использовании возвращаемого значения функции)

По словам Роберто Иерасульского, причина этого относительно небольшого предела 250 - по соображениям производительности. Сохранение размера фрейма стека до 256 означает, что only 8 bits are needed to store a stack frame offset, и поскольку каждый байт-код Lua содержит 2 или 3 из этих смещений стека в качестве параметров, использование меньшего количества байтов для хранения смещений очень важно.

Как проехать более 250 параметров функции

Возвращаясь к первоначальному вопросу, то на самом деле можно передать более 256 параметров в VARIADIC функции. Если вместо использования большого количества параметров, разделенных запятыми, вы распаковываете таблицу или используете какую-либо другую функцию, которая возвращает несколько результатов, тогда нам нужно ограничить размер всего стека Lua, а не размер одного стекового кадра.Это ограничение (LUA_MAXSTACK) настраивается пользователем в luaconf.h и по умолчанию его 1000000.

function rep(n) 
    local t = {} 
    for i = 1, n do 
    t[i] = i 
    end 
    return t 
end 

function foo(...) 
end 

foo(table.unpack(rep(999986))) -- Pretty close to 1000000 

: Помните, что все тело скрипта Lua ведет себя так, как будто это было внутри функции так Lua «toplevel» по-прежнему зависит от ограничений «фрейма стека».

+0

Ничего себе, это действительно здорово! Значит ли это, что таблица будет разделена на несколько кадров стека, если она содержит более 249 элементов? – Rhexis

+0

Думаю, что так. Но, конечно, я должен признаться, что мне нужно будет проверить генерируемый байт-код, чтобы увидеть, как все связывается. – hugomg