命名參數

lua-users home
wiki

Lua 支援通過將資料表傳遞給函式來命名參數。PiL Chap 5 描述了這個概念 [1]。因此,下列搭配位置參數的函式和呼叫

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)

請參閱


RecentChanges · 喜好設定
編輯 · 歷史記錄
最後編輯時間:2012 年 3 月 13 日上午 4:17 GMT (diff)