f [arg1, arg2, …, argN] kontra f [{arg1, arg2, …, argN}]

Próbuję odtworzyć API funkcji (napisanej w R), która przyjmuje dowolną liczbę argumentów i obsługuje ją tak samo, jak obsługiwałaby pojedynczy argument, to lista różnych zestawów danych.

Czy istnieje idiom Mathematica, który pozwala na zdefiniowanie funkcji w taki sposób, aby:

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

zachowywał się to samo co

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

?

Komentarze

  • Możesz po prostu napisać f[args___]:= f[{args}], a następnie podaj definicję f[{arg1_, arg2_,...}].

Odpowiedź

Jak opisał Andy Ross w komentarzu, możesz utworzyć definicję, która wstępnie przetwarza argument (y) do postaci kanonicznej. Odwracając swój przykład, by zilustrować elastyczność:

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

Prawda

Ta metoda jest użyteczna przy bardziej skomplikowanym przetwarzaniu wstępnym, ale w takich prostych przypadkach często łatwiej jest użyć Alternatives:

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

Prawda

Pamiętaj, że kiedy używając Alternatives, musisz ręcznie zamówić wzorce, ponieważ są one wypróbowywane po kolei. Wzorzec args__ | {args__} nie działałby zgodnie z oczekiwaniami, ponieważ args__ dopasuje {12, 7, 3} jako pojedynczy argument .

Odpowiedź

Jest wiele sposobów, aby sobie z tym poradzić. Podejście, które najprawdopodobniej wybrałbym, można zilustrować następującym przykładem:

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

Oczywiście każde zastosowanie tej techniki zastąpiłoby łańcuchy widoczne tutaj działanie odpowiednie do własnych potrzeb.

Innym podejściem jest napisanie oddzielnych funkcji dla każdego wzorca argumentu, który chcesz obsłużyć:

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

Komentarze

  • Jakie jest Twoje uzasadnienie dla " najprawdopodobniej " przy użyciu Switch w przypadku wielu definicji? Switch jest zwykle wolniejsze i nie powinno być używane bez powodu, IMHO.
  • @ Mr.Wizard. Używanie Switch przemawia do mojego poczucia estetyki programowania, ponieważ organizuje wszystkie alternatywy tak, aby można je było obsłużyć w jednej funkcji. Ja ' zwykle nie przejmuję się szybkością wykonywania – dopiero wtedy, gdy powolne wykonywanie staje się naprawdę oczywiste.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *