Optional benannte Argumente in Mathematica
-
06-07-2019 - |
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.
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]
entsprichtOptionValue[f,name]
, wof
der Kopf der linken Seite der Transformationsvorschrift ist, in demOptionValue[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. *)