6
$\begingroup$

I recently asked a question on which I need to use a function with variable number of arguments.

But as I am trying to solve my problem I just wondered : what are the advantages of using a function with variable number of arguments (using the notation f[x__]) whereas using a function that takes a list as a parameter (because a list can have any number of elements).

Does the first method allows more flexibility or both can answers the exact same problems ?

$\endgroup$
  • 1
    $\begingroup$ It is a vague and general question. What answer are you expecting ? $\endgroup$ – Lotus Jun 20 '17 at 11:03
  • 1
    $\begingroup$ I found it quite clear, it touches on quite an advanced subject. I say leave open. $\endgroup$ – LLlAMnYP Jun 22 '17 at 6:32
5
$\begingroup$

Yes, the first method does allow more flexibility, specifically with regard to attributes.

  • HoldFirst, HoldRest, and HoldAll allow you to specify which parameters are held.

  • Listable provides special treatment of Lists, including distribution e.g. f[{1, 2, 3}, x]

  • Orderless provides automatic sorting of arguments and integrates with pattern matching.

Built-in functions that accept other functions often assume that they take multiple arguments. For example if you define your function f[a_, b_] := ... you can use:

  • Array[f, {2, 3}]
  • Fold[f, {a, b, c}]
  • MapIndexed[f, {1, 2, 3}]
  • MapThread[f, {{1, 2}, {x, y}}]
  • Outer[f, {1, 2}, {a, b}]
  • Inner[f, {a, b}, {x, y}]

etc. None of these will work right with f[{a_, b_}] := ...

$\endgroup$
4
$\begingroup$

It's good to think deeply about reasons for implementation details. I'll throw in an example and, hopefully others will contribute in greater detail.

Some internal functions, such as Times or Plus (as I showed in your previous question) take not a list, but a sequence of arguments.

If your definition of your f[x__] contains a lot of Times[x] and Plus[x] or similar things, it might make sense to prefer using f[x__] rather than f[x_List] and then doing Sequence @@ x everywhere. If, on the other hand, the right hand side does better with lists, of course the latter definition makes more sense, so the general answer is "it depends".

You can do even better, though, by using more advanced pattern constructs:

f[a:{x__}] := Plus[x]
f[a:{x__}] := Total[a]

The two definitions above give the same result, but access different things (the first extracts every element out of the list and feeds it to Plus, the latter takes the entire List that we named a as a whole and feeds it to Total. This behavior may have important implications for performance (packed arrays), but I'll leave this part of the discussion for someone else to answer in detail.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.