Frage

Was ist die beste / kanonische Weise eine Funktion mit optionalen benannten Argumenten zu definieren? Um es konkret zu machen, lassen Sie sich eine Funktion foo mit benannten Argumenten a erstellen, b und c, die standardmäßig auf 1, 2 und 3. Zum Vergleich ist hier eine Version von foo mit Positionsargumenten:

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

Hier ist Beispiel Ein- und Ausgabe für die benannte Argumente Version von foo:

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

Es sollte natürlich auch leicht sein Positions Argumente zu haben, bevor die genannten Argumente.

War es hilfreich?

Lösung

finde ich den Standard so, wie es in der Mathematica-Dokumentation zu tun: http: // Referenz .wolfram.com / Mathematica / tutorial / SettingUpFunctionsWithOptionalArguments.html

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

Die Eingabe von „Option“ jedes Mal ist ein wenig umständlich. Aus irgendeinem Grund kann man nicht nur eine globale Abkürzung wie ov = OptionValue machen, aber Sie können dies tun:

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

Oder diese:

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

Oder diese:

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

foo[OptionsPattern[]] := bar[ov@a, ov@b, ov@c]

Andere Tipps

Ja, das kann OptionValue ein bisschen schwierig sein, da ist auf einem Stück Magie beruht, so dass

  

OptionValue[name] entspricht OptionValue[f,name], wo f der Kopf der linken Seite der Transformationsvorschrift ist, in dem OptionValue[name] erscheint.

Werfen in einem expliziten Automatic in der Regel funktioniert der Trick, so in Ihrem Fall würde ich sagen, dass die Lösung ist:

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

Durch die Art und Weise, verwendete Optionen durch Abgleich durchgeführt werden, opts:___?OptionQ und dann Option Werte manuell als {a,b,c}/.Flatten[{opts}] zu finden. Die Musterprüfung OptionQ ist nach wie vor um (wenn auch nicht dokumentiert), aber der OptionValue Ansatz hat den Vorteil, dass Sie Warnungen für nicht existierende Optionen zu erhalten (zum Beispiel foo[d->3]). Dies wäre auch der Fall für die zweite Antwort sein, aber nicht für die, die Sie angenommen haben.

Ich werde diese mögliche Lösung in den Mix werfen:

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]]
]

Ich mag es für seine Prägnanz, aber ich glaube nicht, dass der normale Weg ist. Fallstricke mit sich, dass die Art und Weise zu tun?

PS, verwendet es die folgende praktische Anwendung, Funktion:

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.       *)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top