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.

Était-ce utile?

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 laquelle OptionValue [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.       *)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top