13

オプションの名前付き引数を持つ関数を定義するための最良/標準的な方法は何ですか? 具体的にするために、foo名前付き引数ab、およびを持つ関数を作成しましょうc。デフォルトはそれぞれ 1、2、および 3 です。比較のために、foo位置引数付きのバージョンを次に示します。

foo[a_:1, b_:2, c_:3] := bar[a,b,c]

の名前付き引数バージョンの入力と出力の例を次に示しますfoo

foo[]                  --> bar[1,2,3]
foo[b->7]              --> bar[1,7,3]
foo[a->6, b->7, c->8]  --> bar[6,7,8]

もちろん、名前付き引数の前に位置引数を指定することも簡単です。

4

3 に答える 3

12

Mathematica のドキュメントで標準的な方法を見つけました: http://reference.wolfram.com/mathematica/tutorial/SettingUpFunctionsWithOptionalArguments.html

Options[foo] = {a->1, b->2, c->3};  (* defaults *)
foo[OptionsPattern[]] := bar[OptionValue@a, OptionValue@b, OptionValue@c]

毎回「OptionValue」と入力するのは少し面倒です。何らかの理由で、次のようなグローバルな省略形を作成することはできませんov = OptionValueが、次のようにすることができます。

foo[OptionsPattern[]] := Module[{ov},
  ov[x___] := OptionValue[x];
  bar[ov@a, ov@b, ov@c]]

またはこれ:

With[{ov = OptionValue},
  foo[OptionsPattern[]] := bar[ov@a, ov@b, ov@c]
]

またはこれ:

$PreRead = ReplaceAll[#, "ov" -> "OptionValue"] &;

foo[OptionsPattern[]] := bar[ov@a, ov@b, ov@c]
于 2009-10-23T21:53:15.307 に答える
6

はい、OptionValue魔法のかけらに依存しているため、少し注意が必要です。

OptionValue[name]は に相当しますOptionValue[f,name]。ここで、は に現れるf変換規則の左辺の先頭です。OptionValue[name]

通常、明示的にスローするとAutomaticうまくいくので、あなたの場合、解決策は次のとおりです。

Options[foo] = {a -> 1, b -> 2, c -> 3};
foo[OptionsPattern[]] := 
  bar @@ (OptionValue[Automatic, #] &) /@ First /@ Options[foo] 

ところで、以前はオプションは にマッチしてからopts:___?OptionQとしてオプション値を手動で見つけていまし{a,b,c}/.Flatten[{opts}]た。パターン チェックOptionQはまだありますが (文書化されていません)、このOptionValueアプローチには、存在しないオプション (例: ) に対して警告が表示されるという利点がありますfoo[d->3]。これは 2 番目の応答にも当てはまりますが、受け入れた応答には当てはまりません。

于 2010-02-19T06:40:22.300 に答える
1

この可能な解決策をミックスに投入します。

foo[opts___Rule] := Module[{f},
  f@a = 1; (* defaults... *)
  f@b = 2;
  f@c = 3;
  each[a_->v_, {opts}, f@a = v];

  Return[bar[f@a, f@b, f@c]]
]

私はその簡潔さが好きですが、それが標準的な方法だとは思いません。そのようにすることに問題はありますか?

PS、次の便利なユーティリティ関数を使用します。

SetAttributes[each, HoldAll];                (* each[pattern, list, body]     *)
each[pat_, lst_, bod_] :=                    (*  converts pattern to body for *)
  Scan[Replace[#, pat:>bod]&, Evaluate@lst]  (*   each element of list.       *)
于 2009-10-23T20:58:40.030 に答える