2
$\begingroup$

If a function has e.g. 5 input arguments (a,b,c,d,e), how can I omit to specify only argument c, so that its default value is taken, but the other arguments should be passed to the function?

E.g:

f[a_:1,b_:2,c_:3,d_:4,e_:5]:=a+b+c+d+e;

Is something like the following call possible? What has to to be used at place of Default?

f[7,8,Default,9,10]
$\endgroup$
0

2 Answers 2

7
$\begingroup$

Here's another way to do it, don't go for default values, but use Options instead.

ClearAll@f;
Options[f] = {"a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4, "e" -> 5};
f[OptionsPattern[]] := 
 OptionValue["a"] + OptionValue["b"] + OptionValue["c"] + 
  OptionValue["d"] + OptionValue["e"]
f["a" -> 7, "b" -> 8, "d" -> 9, "e" -> 10]
(* 37 *)
$\endgroup$
3
  • $\begingroup$ No, those extra letters cost me the answer lol $\endgroup$
    – Jason B.
    Commented Mar 23, 2016 at 16:35
  • $\begingroup$ This is what I was looking for ... thanks a lot (again) to you. $\endgroup$
    – mrz
    Commented Mar 23, 2016 at 17:19
  • $\begingroup$ Your code works also without the quotes ... I substituted "a" by a, etc. $\endgroup$
    – mrz
    Commented Mar 24, 2016 at 5:09
5
$\begingroup$

I doubt that this is possible natively (although I'd be happy to be corrected on that and will delete my answer in that case). You can sort of roll your own, with a bunch of definitions of f:

Clear[f, dflt];
f[dflt, b_, c_, d_, e_] := f[1, b, c, d, e]
f[a_, dflt, c_, d_, e_] := f[a, 2, c, d, e]
f[a_, b_, dflt, d_, e_] := f[a, b, 3, d, e]
f[a_, b_, c_, dflt, e_] := f[a, b, c, 4, e]
f[a_, b_, c_, d_, dflt] := f[a, b, c, d, 5]
f[a_, b_, c_, d_, e_] := a + b + c + d + e

f[7, 8, dflt, 9, 10]
(* 37 *)
7 + 8 + 3 + 9 + 10
(* 37 *)

This is only meant as a starting point.

One can generate these automatically from a given pattern and definition. Doing so in a completely general way might be quite an undertaking, but here is a solution which at least works if all patterns are simple Blanks and they all have a default value:

ClearAll[dflt, generateDefaults]
SetAttributes[generateDefaults, HoldAll]
generateDefaults[pattern_, result_] := 
  Module[{head = Head@pattern, args = List @@ pattern, defs, vals},
    defs = head @@ (args /. Verbatim@# -> dflt) & /@ args;
    vals = head @@ (args[[All, 1, 1]] /. #[[1, 1]] -> Last@#) & /@ args;
    MapThread[SetDelayed, {defs, vals}];
    pattern := result
  ]

This will also set default values on the individual definitions, such that omitting elements from the end also works.

As the answers on the duplicate mention, instead of dflt you could use Null which would allow you to omit the argument altogether and call the function like

f[7, 8, , 9, 10]
$\endgroup$

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