Jag försöker återge API: et för en funktion (skriven i R) som accepterar ett godtyckligt antal argument och hanterar det på samma sätt som det skulle hantera ett enda argument som är en lista över olika datamängder.
Finns det ett Mathematica-idiom som gör att en funktion kan definieras så att:
f[ arg1, arg2, ..., argN ]
beter sig samma som
f[ {arg1, arg2, ..., argN} ]
?
Kommentarer
Svar
Som beskrivs av Andy Ross i en kommentar kan du göra en definition som förbehandlar argumenten till en kanonisk form. Att vända på hans exempel för att illustrera flexibilitet:
f[{args__}] := f[args] f[args__] := Multinomial[args] / Plus[args] f[{12, 7, 3}] == f[12, 7, 3]
True
Denna metod är användbar för mer komplicerad förbehandling, men i enkla fall som detta är det ofta lättare att använda Alternatives
:
g[{args__} | args__] := Multinomial[args]/Plus[args] g[{12, 7, 3}] == g[12, 7, 3]
True
Var medveten om att när med Alternatives
måste du manuellt beställa mönstren, för de prövas i följd. Mönstret args__ | {args__}
fungerar inte som önskat eftersom args__
matchar {12, 7, 3}
som ett enda argument .
Svar
Det finns många sätt att hantera detta. Det tillvägagångssätt som jag sannolikt skulle ta kan illustreras med följande exempel:
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" *)
Naturligtvis skulle varje tillämpning av denna teknik ersätta strängarna som ses här med några åtgärd som passar sina egna behov.
Ett annat tillvägagångssätt är att skriva separata funktioner för varje argumentmönster du vill hantera:
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" *)
Kommentarer
- Vad resonerar du för " troligtvis " med
Switch
över flera definitioner?Switch
är vanligtvis långsammare och bör inte användas utan anledning, IMHO. - @ Mr.Wizard. Att använda
Switch
tilltalar min känsla av att programmera estetik eftersom den organiserar alla alternativ så att de kan hanteras i en enda funktion. Jag ' Jag brukar inte alla som berör exekveringshastighet – inte förrän långsam körning blir riktigt tydlig.
f[args___]:= f[{args}]
och ange sedan definitionen förf[{arg1_, arg2_,...}]
.