Jeg prøver å reprodusere API for en funksjon (skrevet i R) som godtar et vilkårlig antall argumenter og håndterer det på samme måte som det ville håndtere et enkelt argument som er en liste over forskjellige datasett.
Er det et Mathematica-idiom som gjør det mulig å definere en funksjon slik at:
f[ arg1, arg2, ..., argN ]
oppfører seg det samme som
f[ {arg1, arg2, ..., argN} ]
?
Kommentarer
Svar
Som beskrevet av Andy Ross i en kommentar, kan du lage en definisjon som forbehandler argumentet / argumentene til en kanonisk form. Å snu eksemplet hans bare for å illustrere fleksibilitet:
f[{args__}] := f[args] f[args__] := Multinomial[args] / Plus[args] f[{12, 7, 3}] == f[12, 7, 3]
True
Denne metoden er nyttig for mer komplisert forbehandling, men i enkle tilfeller som dette er det ofte enklere å bruke Alternatives
:
g[{args__} | args__] := Multinomial[args]/Plus[args] g[{12, 7, 3}] == g[12, 7, 3]
True
Vær oppmerksom på at når ved hjelp av Alternatives
må du manuelt bestille mønstrene, for de blir prøvd i rekkefølge. Mønsteret args__ | {args__}
fungerer ikke som ønsket fordi args__
vil matche {12, 7, 3}
som et enkelt argument .
Svar
Det er mange måter å håndtere dette på. Tilnærmingen jeg mest sannsynlig vil ta kan illustreres med følgende eksempel:
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" *)
Selvfølgelig vil hver anvendelse av denne teknikken erstatte strengene som er sett her med noen handling som passer for sine egne behov.
En annen tilnærming er å skrive separate funksjoner for hvert argumentmønster du vil håndtere:
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
- Hva er begrunnelsen din for " mest sannsynlig " ved hjelp av
Switch
over flere definisjoner?Switch
er vanligvis tregere og bør ikke brukes uten grunn, IMHO. - @ Mr.Wizard. Å bruke
Switch
appellerer til min følelse av å programmere estetikk fordi den organiserer alle alternativene slik at de kan håndteres i en enkelt funksjon. Jeg ' Jeg pleier ikke å bekymre meg for kjøringshastighet – ikke før langsom kjøring blir virkelig tydelig.
f[args___]:= f[{args}]
og deretter gi definisjonen forf[{arg1_, arg2_,...}]
.