f [arg1, arg2, …, argN] vs. f [{arg1, arg2, …, argN}]

Ik probeer de API van een functie (geschreven in R) te reproduceren die een willekeurig aantal argumenten accepteert en deze op dezelfde manier afhandelt als een enkel argument dat is een lijst met verschillende datasets.

Is er een Mathematica-idioom waarmee een functie kan worden gedefinieerd zodat:

f[ arg1, arg2, ..., argN ] 

zich gedraagt hetzelfde als

f[ {arg1, arg2, ..., argN} ] 

?

Reacties

  • Je zou gewoon kunnen schrijven f[args___]:= f[{args}] en geef vervolgens de definitie voor f[{arg1_, arg2_,...}].

Antwoord

Zoals beschreven door Andy Ross in een opmerking, kun je een definitie maken die het argument (en) voorbewerkt tot een canonieke vorm. Zijn voorbeeld omdraaien om flexibiliteit te illustreren:

f[{args__}] := f[args] f[args__] := Multinomial[args] / Plus[args] f[{12, 7, 3}] == f[12, 7, 3] 

Waar

Deze methode is handig voor meer gecompliceerde voorverwerking, maar in eenvoudige gevallen zoals deze is het vaak gemakkelijker om Alternatives te gebruiken:

g[{args__} | args__] := Multinomial[args]/Plus[args] g[{12, 7, 3}] == g[12, 7, 3] 

Waar

Houd er rekening mee dat wanneer door Alternatives te gebruiken, moet u de patronen handmatig bestellen, want ze worden op volgorde geprobeerd. Het patroon args__ | {args__} zou niet werken zoals gewenst omdat args__ overeenkomt met {12, 7, 3} als een enkel argument .

Antwoord

Er zijn veel manieren om hiermee om te gaan. De benadering die ik hoogstwaarschijnlijk zou volgen, kan worden geïllustreerd door het volgende voorbeeld:

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" *) 

Natuurlijk zou elke toepassing van deze techniek de hier getoonde strings vervangen door enkele actie passend bij zijn eigen behoeften.

Een andere benadering is om afzonderlijke functies te schrijven voor elk argumentpatroon dat u wilt behandelen:

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" *) 

Opmerkingen

  • Wat is uw redenering voor " hoogstwaarschijnlijk " met Switch over meerdere definities? Switch is gewoonlijk langzamer en mag niet zonder reden worden gebruikt, IMHO.
  • @ Mr.Wizard. Het gebruik van Switch spreekt mijn gevoel voor programmeeresthetiek aan omdat het alle alternatieven organiseert zodat ze in één enkele functie kunnen worden behandeld. Ik ' ben meestal niet zo bezorgd over de uitvoeringssnelheid – niet voordat de trage uitvoering echt duidelijk wordt.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *