2009-10-23 16 views
10

¿Cuál es la mejor forma/canónica de definir una función con argumentos con nombre opcionales? Para hacerlo más concreto, creemos una función foo con los argumentos con nombre a, b y c, que por defecto son 1, 2 y 3, respectivamente. Para la comparación, he aquí una versión de foo con argumentos posicionales:Argumentos con nombre opcionales en Mathematica

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

Aquí se introduce la muestra y de salida para la versión de argumentos con nombre de foo:

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

Se debe, por supuesto también ser fácil tener argumentos posicionales antes de los argumentos nombrados.

+0

Ver también: http: // stackoverflow.com/questions/4682742/optional-named-arguments-without-wrapping-them-all-in-optionvalue – dreeves

Respuesta

10

he encontrado la forma estándar de hacerlo en la documentación de Mathematica: http://reference.wolfram.com/mathematica/tutorial/SettingUpFunctionsWithOptionalArguments.html

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

Typing "ValorDeLaOpción" cada vez que hay una poco engorroso. Por alguna razón no se puede simplemente hacer una abreviatura global como ov = OptionValue pero se puede hacer esto:

foo[OptionsPattern[]] := Module[{ov}, 
    ov[x___] := OptionValue[x]; 
    bar[[email protected], [email protected], [email protected]]] 

O esto:

With[{ov = OptionValue}, 
    foo[OptionsPattern[]] := bar[[email protected], [email protected], [email protected]] 
] 

O esto:

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

foo[OptionsPattern[]] := bar[[email protected], [email protected], [email protected]] 
+0

Acerca de la tipificación engorrosa de OptionValue: en este caso podría decir 'In [32]: = OptionValue/@ bar [a, b, c] Out [32] = bar [OptionValue [a], OptionValue [b], OptionValue [c]] ' –

+0

@dreeves Hay una forma más concisa del último bloque de código usando' With' en vez de ' Módulo'. ¿Puedo editar tu respuesta para agregar esto? –

+0

@Sjoerd gracioso, tu comentario no estaba allí cuando cargué esta página. Supongo que también estás leyendo estas publicaciones antiguas. –

2

Voy a tirar esta posible solución en la mezcla:

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

    Return[bar[[email protected], [email protected], [email protected]]] 
] 

me gusta por su concisión, pero no creo que es la manera estándar. ¿Algún problema con hacerlo de esa manera?

PS, utiliza la siguiente función de utilidad práctica:

SetAttributes[each, HoldAll];    (* each[pattern, list, body]  *) 
each[pat_, lst_, bod_] :=     (* converts pattern to body for *) 
    Scan[Replace[#, pat:>bod]&, [email protected]] (* each element of list.  *) 
4

Sí, OptionValue puede ser un poco complicado porque se basa en una pieza de magia para que

OptionValue[name] es equivalente a OptionValue[f,name], donde f es el encabezado del lado izquierdo de la regla de transformación en la que aparece OptionValue[name].

Lanzar en una explícita Automatic por lo general hace el truco, por lo que en su caso, diría que la solución es:

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

Por cierto, las opciones que se utilizan para hacer emparejando a opts:___?OptionQ, y luego encontrar valores de opciones manualmente como {a,b,c}/.Flatten[{opts}]. La comprobación de patrón OptionQ sigue disponible (aunque no está documentada), pero el enfoque OptionValue tiene la ventaja de que recibe advertencias para las opciones que no existen (por ejemplo, foo[d->3]). Este también sería el caso para su segunda respuesta, pero no para la que ha aceptado.

Cuestiones relacionadas