f [arg1, arg2, …, argN] frente a f [{arg1, arg2, …, argN}]

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

  • Podrías simplemente escribir f[args___]:= f[{args}] y luego proporcione la definición de f[{arg1_, arg2_,...}].

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.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *