# How to check the number of function arguments given by the user

Suppose I have defined the following function inside a package that can take 2 arguments.

f[x_,y_]:={x,y}


So, if the user gives f[1,2] then the output is {1,2}. But if the input is f[1,2,3] then the output is also f[1,2,3].

I want to print an error message when the input is f[1,2,3], but I can't figure out how to count the number of arguments given by the user.

You can redefine your function f to accept a variable number of arguments (x__) and then check the length with Length.

Clear[f];
f::argerr = "Two arguments expected, but 1 given.";
f[x__] :=
If[Length@List@x == 2, List@x,
Message[f::argerr, Length@List@x]; $Failed]; f[1, 2] (* {1, 2} *) f[1, 2, 3] (* f::argerr: Two arguments expected, but 3 given. *) (*$Failed *)


Another, probably a more appropriate way, as suggested in the comment by Jason, is to use CheckArguments.

Clear[f];
f[x_, y_] := {x, y};
f[args___] := Null /; CheckArguments[f[args], 2]

f[1, 2]
(* {1, 2} *)

f[1, 2, 3]
(* f::argrx: f called with 3 arguments; 2 arguments are expected. *)
(* f[1, 2, 3] *)


# Why create an error if you already have the necessary arguments to proceed?

It seems everywhere I look coders especially new ones are eager to throw errors even when there are still easy workarounds. The end-user may not even be a programmer. Think of them as your customers. They may not think too kindly with using applications that are too sensitive to errors instead of self-correcting when possible.

My preferred approach is to always avoid error when possible. Here we can drop (not ignore) trailing arguments from evaluation but the end-user must always be alerted (warned) so he can decide if the output is still useful. A nice user-friendly way is to alert with an Echo[warning message] which looks very similar to error messages. These are hard to ignore but we can still proceed with evaluation.

Notice how much cleaner the code is now and as a bonus it is self-correcting. That is a win-win for everyone. You put out a better product and code is easier to manage.

## 1. A Good Approach: 1 Definition

Remove[f];
f[x_, y_, z___] := Block[
{
msg="2 args expected pos 3 not included in evaluation."
},
If[Length@{z} > 0, Echo@msg];
{x, y}
];

f[1, 2, 3]

{1, 2}

>> 2 args expected pos 3 not included in evaluation .


## 2. Even Better: Recursive Calls

(* definitions *)
Remove@f;
f[x_, y_,
z__] := (Echo[{z}, "2 args expected, pos 3 dropped \[Rule]"];
f[x, y]);
f[x_, y_] := {x, y};

(* input *)
seq = Range[1, 5] /. List -> Sequence;
f[seq](* this is just f[1,2,3,4,5] *)
f[a, b]
f[0, 0]

(* output *)
>>2 args expected, pos 3 dropped ->  {3,4,5}

{1,2}

{a,b}

{0,0}