Arguments nommés facultatifs dans Mathematica
-
06-07-2019 - |
Question
Quel est le meilleur moyen / canonique de définir une fonction avec des arguments nommés facultatifs? Pour le rendre concret, créons une fonction toto
avec les arguments nommés a
, b
et c
, qui par défaut à 1, 2 et 3, respectivement. À titre de comparaison, voici une version de toto
avec des arguments de position:
foo[a_:1, b_:2, c_:3] := bar[a,b,c]
Voici un exemple d'entrée et de sortie pour la version à arguments nommés de toto
:
foo[] --> bar[1,2,3]
foo[b->7] --> bar[1,7,3]
foo[a->6, b->7, c->8] --> bar[6,7,8]
Bien sûr, il devrait également être facile d’avoir des arguments de position avant les arguments nommés.
La solution
J'ai trouvé le moyen standard de le faire dans la documentation Mathematica: http: // référence .wolfram.com / mathematica / tutorial / SettingUpFunctionsWithOptionalArguments.html
Options[foo] = {a->1, b->2, c->3}; (* defaults *)
foo[OptionsPattern[]] := bar[OptionValue@a, OptionValue@b, OptionValue@c]
Dactylographie " OptionValue " chaque fois est un peu lourd. Pour une raison quelconque, vous ne pouvez pas créer une abréviation globale telle que ov = OptionValue
, mais vous pouvez le faire:
foo[OptionsPattern[]] := Module[{ov},
ov[x___] := OptionValue[x];
bar[ov@a, ov@b, ov@c]]
Ou ceci:
With[{ov = OptionValue},
foo[OptionsPattern[]] := bar[ov@a, ov@b, ov@c]
]
Ou ceci:
$PreRead = ReplaceAll[#, "ov" -> "OptionValue"] &;
foo[OptionsPattern[]] := bar[ov@a, ov@b, ov@c]
Autres conseils
Oui, OptionValue
peut être un peu délicat car il repose sur un brin de magie pour que
OptionValue [nom]
est équivalent àOptionValue [f, nom]
, oùf
correspond à l'en-tête du côté gauche de la règle de transformation dans laquelleOptionValue [nom]
apparaît.
Ajouter un Automatique
explicite fait généralement l'affaire, donc dans votre cas, je dirais que la solution est la suivante:
Options[foo] = {a -> 1, b -> 2, c -> 3};
foo[OptionsPattern[]] :=
bar @@ (OptionValue[Automatic, #] &) /@ First /@ Options[foo]
Soit dit en passant, les options étaient habituellement utilisées en faisant correspondre à opts: ___? OptionQ
, puis en recherchant les valeurs d'options manuellement sous la forme {a, b, c} /. Flatten [{ opte}]
. La vérification du modèle OptionQ
est toujours disponible (bien que non documentée), mais l'approche OptionValue
offre l'avantage de vous donner des avertissements pour les options non existantes (par exemple, foo [ d- & 3)
). Ce serait également le cas pour votre deuxième réponse, mais pas pour celle que vous avez acceptée.
Je jetterai cette solution possible dans le mix:
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]]
]
J'aime ça pour sa brièveté mais je ne pense pas que ce soit la manière habituelle. Avez-vous eu le courage de le faire de cette façon?
PS, il utilise la fonction utilitaire suivante:
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. *)