Estoy tratando de reproducir la API de una función (escrita en R) que acepta un número arbitrario de argumentos y lo maneja de la misma manera que manejaría un solo argumento que es una lista de diferentes conjuntos de datos.
¿Existe un modismo de Mathematica que permite definir una función para que:
f[ arg1, arg2, ..., argN ]
se comporte lo mismo que
f[ {arg1, arg2, ..., argN} ]
?
Comentarios
Respuesta
Como describió Andy Ross en un comentario, puede hacer una definición que preprocesa los argumentos en una forma canónica. Cambiando su ejemplo simplemente para ilustrar la flexibilidad:
f[{args__}] := f[args] f[args__] := Multinomial[args] / Plus[args] f[{12, 7, 3}] == f[12, 7, 3]
Verdadero
Este método es útil para un preprocesamiento más complicado, pero en casos simples como este, a menudo es más fácil de usar Alternatives
:
g[{args__} | args__] := Multinomial[args]/Plus[args] g[{12, 7, 3}] == g[12, 7, 3]
Verdadero
Tenga en cuenta que cuando usando Alternatives
debe ordenar los patrones manualmente , ya que se prueban en secuencia. El patrón args__ | {args__}
no funcionaría como se desea porque args__
coincidirá con {12, 7, 3}
como un solo argumento .
Respuesta
Hay muchas formas de manejar esto. El enfoque que probablemente tomaría se puede ilustrar con el siguiente ejemplo:
f[seqn : ___] := Module[{args = {seqn}}, Switch[args, {{___}}, "List of args", {_}, "One arg", {_, __}, "Two or more args", {}, "No args" ]] f[{x, y, z}] (* ==> "List of args" *) f[{x}] (* ==> "List of args" *) f[] (* ==> "No args" *) f[x] (* ==> "One arg" *) f[x, y, z] (* ==> "Two or more args" *)
Por supuesto, cada aplicación de esta técnica reemplazaría las cadenas que se ven aquí con algunas acción apropiada a sus propias necesidades.
Otro enfoque es escribir funciones separadas para cada patrón de argumento que desee manejar:
g[args : {___}] := "List of args" g[] := "No args" g[arg_] := "One arg" g[arg_, rest__] := "Two or more args" g[{x, y, z}] (* ==> "List of args" *) g[{x}] (* ==> "List of args" *) g[] (* ==> "No args" *) g[x] (* ==> "One arg" *) g[x, y, z] (* ==> "Two or more args" *)
Comentarios
- ¿Cuál es su razonamiento para " más probablemente " usando
Switch
sobre varias definiciones?Switch
suele ser más lento y no debe usarse sin motivo, en mi humilde opinión. - @ Mr.Wizard. El uso de
Switch
apela a mi sentido de la estética de la programación porque organiza todas las alternativas para que puedan tratarse en una única función. Yo ' generalmente no estoy tan preocupado por la velocidad de ejecución, no hasta que la ejecución lenta se vuelve realmente evidente.
f[args___]:= f[{args}]
y luego proporcione la definición def[{arg1_, arg2_,...}]
.