関数の引数のデフォルト値を定義する


86

Lua wikiで、欠落している引数のデフォルト値を定義する方法を見つけました。

function myfunction(a,b,c)
    b = b or 7
    c = c or 5
    print (a,b,c)
end

それが唯一の方法ですか?PHPスタイルmyfunction (a,b=7,c=5)が機能していないようです。Luaの方法が機能しないわけではありませんが、これが唯一の方法かどうか疑問に思っています。

回答:


86

名前付き引数とPHPやPythonなどのデフォルト値が必要な場合は、テーブルコンストラクターを使用して関数を呼び出すことができます。

myfunction{a,b=3,c=2}

(これは、次のようなLuaの多くの場所で見られるLuaSocketのプロトコルモジュールの高度形態およびコンストラクタIUPLua。)

関数自体は、次のようなシグネチャを持つことができます。

function myfunction(t)
    setmetatable(t,{__index={b=7, c=5}})
    local a, b, c =
      t[1] or t.a, 
      t[2] or t.b,
      t[3] or t.c
    -- function continues down here...
end

パラメータのテーブルにない値__indexは、メタテーブルのテーブルから取得されます(メタテーブルのドキュメントを参照)。

もちろん、テーブルコンストラクターと関数を使用すると、より高度なパラメータースタイルが可能です。必要なものは何でも記述できます。例えば、ここではパラメータ名とデフォルト値と通常の引数リストを取る関数を定義テーブルから名前付きまたは-位置引数テーブルを取る関数を構築する機能です。

非言語レベルの機能として、このような呼び出しを変更して、新しい動作とセマンティクスを提供できます。

  • 複数の名前を受け入れるように変数を作成できます
  • 位置変数とキーワード変数を散在させることができます-両方を定義すると、どちらかが優先されます(またはエラーが発生します)
  • キーワードのみの位置のない変数、および名前のない位置のみの変数を作成できます
  • 文字列を解析することで、かなり冗長なテーブルの構築を行うことができます。
  • 関数が1つのテーブル以外で呼び出された場合、引数リストを逐語的に使用できます。

引数トランスレータを作成するためのいくつかの便利な関数は、(5.2でunpack移動table.unpack)、setfenv(5.2で新しい_ENV構造で非推奨)、およびselect(指定された引数リストから単一の値、またはリストの長さを返す'#')です。


AIはluaを使い始めたばかりですが、当面はシンプルにしておきますが、あなたの投稿は非常に有益です。後で重宝するかもしれません。ありがとう。
ripat

1
ほとんどの場合、シンプルに保つことが道です。メタパラメータインターフェイスは、多数のオプション属性を持つオブジェクト(UIオブジェクトなど)にのみ実際に必要です。
スチュアートP.ベントレー

この答えは、現在受け入れ済みとしてマークされているものではなく、質問を解決するものだと思います。啓蒙に感謝します:)
2013

1
ことに留意すべきでx or defaultもこの応答に使用される式は本当にパラメータのデフォルト値に真の同等が、両方の場合のみ動作だけで単純な回避策ではないnilfalse無効なパラメータ値です。ブールパラメータのデフォルトxがでtrueあり、呼び出し元が明示的なを渡したとしますfalse。次に、明示的に渡された場合でも、x or trueを与えます。より良いバージョンは、より読みやすいでしょう。ただし、明示的な引数を処理することはできません。truefalseif x == nil then x = default endnil
ジェスパー

ああ、ねえ、これは今受け入れられた答えです!いいね。(記録のために、そして@Undoのコメントを文脈に当てはめると、以下のjpjacobsの回答は、非常に長い間受け入れられた回答でした。2つ目のポピュリストバッジをほぼ取得ました。)
Stuart P. Bentley

46

私の意見では、他の方法はありません。それはルアの考え方です。飾り気がなく、いくつかの糖衣構文を除いて、単純なことを行う冗長な方法はありません。


10
この答えは、関数がテーブルコンストラクターで呼び出される以下のStuart P.Bentleyの答えによって完全に反証されています。これはLuaの強みの1つです。フリルの束はありませんが、Luaの基本的な構成要素により、言語のサイズが小さくシンプルであるため、無限のことができます。
コリンDベネット

@ColinDBennett発言していただきありがとうございます。OPがあなたのコメントを読んだようで、その12月に、受け入れられた回答がそれに応じて変更されました。(そして今、それは明確にするために「上記のスチュアートP.ベントレーの答え」です:ウィンク:)
スチュアートP.ベントレー

21

技術的にはありますがb = b == nil and 7 or b(7falsefalse or 7評価される有効な値の場合に使用する必要があります)、それはおそらくあなたが探しているものではありません。


1
をチェックしていない場合false、より簡単な方法は、変数を最初に配置し、デフォルトを最後に配置することです。b = b or 7
Rebs 2015年

2
OPが彼らの質問でそれを述べたので、私は言及するのは不必要だと思いました(質問は以外の デフォルト変数を定義する方法についてでしたb = b or 7)。
スチュアートP.ベントレー

6

私がこれまでに見つけた、意味のある唯一の方法は、次のようなことをすることです。

function new(params)
  params = params or {}
  options = {
    name = "Object name"
  }

  for k,v in pairs(params) do options[k] = v end

  some_var = options.name
end

new({ name = "test" })
new()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.