2016-08-15 8 views
4

私はモバイルアプリケーション開発の大学クラスでLuaを学習していますが、最近では動的な量の引数を許す省略演算子(...)を扱っています。私は多分考えルア・エリプシス(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) 

:好奇心のうち、私はそれは結局のところ、それは例えば

で、試してみて、それが扱うことができる引数の数には限界があったかどうかを調べることにしましたそれはOSに依存していたか、スタックのサイズに関連していたので、LinuxとWindowsの両方で、それぞれ32ビット版と64ビット版の両方でこれをテストしました。許容される要素の数は248にとどまりました。これはハードコードされた制限のようです。私は> 248をしようとした場合、私は私が手にエラーを取得している:私は誰もが、ほとんどの場合ではなく、そのような場合のために以上の248個の表現を必要と想像カント

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

、これを回避する方法はありますか?また、なぜそれは248ですか?その数字は特別なようではありません。

+0

これは、使用しているLuaのバージョンによって異なります。コロナが5.1または5.2を使用しているかどうか知っていますか? – hugomg

+0

コロナはlua 5.1を使用していますが、これはlonaコードを実行するためにターミナルを使用していましたが、これはlona 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 
) 

をメッセージtoo many arguments passed to functionの代わりにfunction or expression too complexまたはその行に沿って何かが読み取られます。

なぜ248ですか?

スタックフレームの最大サイズは、実際llimits.hにおいて249で、Luaは250にMAXSTACKを定義しlcode.cに、checkstack機能のみより小さいStackFrameを使用することができ..

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

これは実験で得られた結果と一致します。我々はまた、必要があるだろう(私たちが呼んでいるとNは、関数の引数と248 + 1 = 249 < = 250に向けて指すように機能の方に指すように1:関数呼び出しf(a1,a2,...,an)のためのバイトコードはスタック上N+1登録が必要になりますロベルト・イエルサリムズチーによる)

を関数の戻り値を使用している場合、余分なレジスタ、250のこの比較的小さな制限の理由は、パフォーマンス上の理由からです。スタックフレームサイズを256より下に保つことは、only 8 bits are needed to store a stack frame offsetを意味し、各Luaバイトコードは2つまたは3つのスタックオフセットをパラメータとして含んでいるため、オフセットを格納するバイト数を減らすことは非常に重要です。

が戻ってあなたの元の質問に来る関数に250以上のパラメータを渡す方法を

、可変長関数に256以上のパラメータを渡すことが実際に可能です。代わりに、カンマで区切られたパラメータの多くを使用してのあなたは、テーブルを解凍または複数の結果を返す他のいくつかの機能を使用する場合は、私たちが直面しなければならない制限が全体のLuaのサイズではなく、単一のスタックフレームのサイズのスタックです。この制限(LUA_MAXSTACK)は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 

luaconf.hで、デフォルトではユーザ設定可能ですので、それは関数内であるかのようにLuaのスクリプトの全身が動作することを忘れないでくださいLuaの "トップレベル"は依然として "スタックフレーム"の制限の対象です。

+0

うわー、これは本当にクールです!つまり、249を超える要素が含まれていると、複数のスタックフレームに分割されることになります。 – Rhexis

+0

そうだと思います。しかし、すべてがどのように結びついているかを見るためには、生成されたバイトコードをチェックする必要があることを告白する必要があります。 – hugomg