# Optional argument as a correction of a main argument

Let's consider a function

f[a_,b___]


I want that if I input only one argument I get

f[a]=a


but if I input 2 arguments I get

 f[a,b]=2a+b


How can I implement that?

I thought I could use If:

f[a_,b___]:=If[b===Null,a,2a+b]


but reading this previous post Are UnsamQ and Not[SameQ] the same function? I think it's not the correct way.

I could use 2 different definition for f[a_] and f[a_,b_] but I'd like to have only one definition. In fact, my problem arises because if f has only one argument, f performs analytic calculation, but with two argument (where the second argument is a "correction" of the first one) f needs, in only one part, a numerical calculations; anyway the computation that f performs is the same in both cases.

• You should use two definitions, f[a_] := a; f[a_, b__] := 2a+b. In your code, you could use MatchQ[Hold[b], Hold[]] for the condition test. (You could also use SameQ instead of MatchQ.) – Michael E2 May 31 '17 at 10:31
• I agree with previous comment that the simplest way would be to just use two definitions. One more alternative to make do with one could be f[x__] := If[Length[{x}] == 1, First[{x}], 2 First[{x}] + Last[{x}]]. – Kiro May 31 '17 at 10:38

## 1 Answer

Two definitions, as recommended by m_goldberg and Michael E2, really is the preferred solution:

f[a_]     := a
f[a_, b_] := 2 a + b


This is both clear and efficient.

If you prefer an If statement then perhaps:

ClearAll[f]

f[a_, b___] := If[Hold[b] === Hold[], a, 2 a + b]


I am using Hold for generality, as in some cases one would not wish for the arguments to evaluate. That may not matter if f does not itself have a hold attribute but I felt it better to illustrate this than to omit it.

If you want to be clever we can exploit the specific definition of the example and write:

ClearAll[f]

f[a_: 0, b_] := 2 a + b

f[x]
f[x, y]

x

2 x + y


This works by making parameter a Optional with a default value of zero. When it is not provided the term 2 a therefore vanishes from the sum. If this kind of trickery pleases you see also what I call "vanishing patterns."

• My original problem is that I have a function f that is quite complex. In only one part it needs to solve a system of equations. The system can be very complex, depending on the terms in his argument a. So my idea was to put simple terms in the first argument and complex terms in the second one. So if there are complex terms (2nd argument), f uses FindRoot otherwise (when the 2nd argument is absent) Solve; but, apart from this choice FindRoot-Solve all the rest is exactly the same. This is why I was looking for only one function instead than a function and his "copy". – Giancarlo May 31 '17 at 13:27
• So, also in this case, would you suggest to have 2 different functions? – Giancarlo May 31 '17 at 13:27
• @Giancarlo I would need to see the function(s) to give my best recommendation. Probably I would use two definitions but one of them would hand off to the other, passing FindRoot or Solve as a parameter perhaps. – Mr.Wizard May 31 '17 at 13:47
• Well, in my specific case I' ll use the If in this way f[a_, b_:0] := If[b==0,a (*that means using Solve in my case*), 2a+b (*that means using FindRoot in my case*)]. Thank you :) – Giancarlo Jun 1 '17 at 5:56
• sorry, with === instead of ==, that means f[a_, b_:0] := If[b===0,a , 2a+b] – Giancarlo Jun 1 '17 at 7:40