命名參數 |
|
local function pipe(input, output) output:write(input:read'*a') end pipe(io.stdin, io.stdout)
可以用命名參數樣式撰寫成
local function pipe(t) local input = assert(t.input) local output = assert(t.output) output:write(input:read'*a') end pipe({input=io.stdin, output=io.stdout}) pipe{input=io.stdin, output=io.stdout} -- the following shorter syntax is equivalent and preferrred
另外,將執行某些類型的參數檢查,其最基本的型式會包括上述 assert,其餘可能較為複雜,例如 StructuralPatternMatching。函式有可能是同時支援命名和位置呼叫慣例的
local function pipe(...) local input, output if type(...) == 'table' then local t = ... input, output = assert(t.input or t[1]), assert(t.output or t[2]) else input, output = ... end output:write(input:read'*a') end pipe(io.stdin, io.stdout) -- positional form pipe{input=io.stdin, output=io.stdout} -- named form pipe{io.stdin, output=io.stdout} -- mixed form (positional and named) pipe{io.stdin, io.stdout} -- mixed form (using only positional)
選用/預設參數也可以透過支援,如下所示
input, output = assert(t.input or t[1] or io.stdin), assert(t.output or t[2] or io.stdout)
為避免歧義,上述假設第一個位置參數永遠不會是資料表,或至少如果它是一個資料表,則可以將其與命名參數的資料表加以區別。
使用命名或混合參數形式時,程式設計師務必記住將括號從「()」變更為「{}」。
命名形式的一個缺點是資料表建立確實需要一些額外的上層負擔來分配資料表。基準測試可以決定這在實務上有多重要。在必須密集運算的緊密迴圈中,這可能會造成問題。
命名形式的錯誤處理也比較複雜,且程式碼也比較冗長/醜陋,但如果位置參數具有必須檢查的巢狀結構,則會發生同樣的問題。
命名形式不會保留尾部的 nil,因為尾部的 nil 在資料表建構中會被忽略。因此,下列呼叫是無法區分的
f{a,b,nil,d=d}
f{a,b,d=d}
以下是進行命名參數的一些其他比較不傳統的可能方式
f(a, b, {c=c}) f('a',a, 'b',b, 'c',c) -- note: Perl supports a syntactic sugar for this: `a=>$a` is `'a',$a` f(params().a(a).b(b).c(c)) -- C++ chained method call style. f('c,b,a', c,b,a) -- note: parameter resolution can be memoized (see link below) f'c=$(c),b=$(b),a=$(a)' -- variant of above with StringInterpolation [1] syntax sugar for f('c=$(c),b=$(b),a=$(a)',c,b,c)
sum(z=3*i, y=2*i, i)
變成 sum['z,y'](3*i, 2*i, i)
的語法糖,以便命名參數解析可以記錄。命名參數對 LuaJit 最佳化的影響也已探討過。