# How to program a F::argx message?

How useful is it to program a user-built function in a package to produce a red warning message F::argx if you give the wrong number of arguments to that function? How do I do this?

-
have you seen this? – acl Apr 15 '13 at 18:52

The large addendum on handling multiple messages as built-ins do has been moved to a separate post; please see the link below for advanced message handling options.

### Macro package function SetArgumentCount

In recent versions there is an undocumented function MacrosSetArgumentCount that specifically automates creation of a definition for an argument Message. Examples:

MacrosSetArgumentCount[foo, 2]

foo[1]
foo[1, 2, 3]


foo::argr: foo called with 1 argument; 2 arguments are expected.

foo::argrx: foo called with 3 arguments; 2 arguments are expected.

MacrosSetArgumentCount[foo, {2, 4}]

foo[1]
foo[1, 2, 3, 4, 5]


foo::argbu: foo called with 1 argument; between 2 and 4 arguments are expected. >>

foo::argb: foo called with 5 arguments; between 2 and 4 arguments are expected. >>

(Returned input intentionally omitted.)

### Available messages

The message ::argx is one of the general messages intended for use with any function. These have the special property of being called for any symbol used (placed left of ::):

Message[foo::"argx", "foo", 2, 3]


foo::argx: foo called with 2 arguments; 1 argument is expected. >>

Use Messages[General] to see a list of these messages.

### Synax highlighting

SyntaxInformation can be used to create the red syntax highlighting present in many built-in functions. For a full description please see:

### Basic usage

You may have noticed that the method shown in R.M's answer doesn't produce behavior that exactly matches internal functions such as Plot, which echo bad input:

Plot[1, 2, 3, 4]


Plot::nonopt: Options expected (instead of 4) beyond position 2 in Plot[1,2,3,4]. An option must be a rule or a list of rules. >>

Plot[1, 2, 3, 4]


To get this you behavior you can generate the Message as a side-effect, as in Condition:

ClearAll@f
SyntaxInformation[f] = {"ArgumentsPattern" -> {_}};
f[1] := True
f[_] := False
f[x___] /; Message[f::argx, "f", Length@{x}] := Null


Now:

f[1, 2, 3]


f::argx: f called with 3 arguments; 1 argument is expected. >>

f[1, 2, 3]


The final no-match rule can also be written:

x_f /; Message[f::argx, "f", Length @ Unevaluated @ x] := Null

-
You said it didn't produce the same behaviour as in built-ins and that using condition was better... I just don't see it in the example – R. M. Apr 15 '13 at 21:01
@rm-rf Oh. Your catch definition actually matches and returns Message[f::argx, "f", Length@{x} + 1] or rather the Null it produces; my catch definition does not match and produces the message as a side-effect, and therefore the original input is returned. This is how most internal definitions are written. – Mr.Wizard Apr 15 '13 at 21:02
Ah, it keeps the input unevaluated. +1 – R. M. Apr 15 '13 at 21:06
btw, I just remembered why I don't use this in my packages... if you have different messages being thrown based on the form of the input (as I often have), then throwing messages as a side-effect of not matching the form will result in all messages being thrown. – R. M. Apr 16 '13 at 14:32
@ShutaoTang The Message expression is evaluated as part of the Condition. Message itself returns Null, therefore the condition does not match, but by that time the message has already been printed. The RHS is irrelevant in this case. – Mr.Wizard Jun 22 '15 at 7:42

As acl points out, this post shows you how to setup error highlighting for invalid number of arguments. Coming to the actual error messages used, there are three built-in messages attached to General, that can be used for your own functions as well. These are argx, argrx and argt:

General::argx
(* "1 called with 2 arguments; 1 argument is expected." *)

General::argrx
(* "1 called with 2 arguments; 3 arguments are expected." *)

General::argt
(* "1 called with 2 arguments; 3 or 4 arguments are expected." *)


You can attach these messages to your own functions (any message defined for General can be used for any other symbol) like in the following example (shown only for argx):

ClearAll@f
SyntaxInformation[f] = {"ArgumentsPattern" -> {_}};
f[1] := True
f[_] := False
f[_, x__] := Message[f::argx, "f", Length@{x} + 1]


-

Thats what I learned.
To see if my function has just 2 arguments, not 1 argument and no more the 2 arguments I did these steps:
Define the warnings

General::twoplus = "f called with to much arguments, 2 argument expected.";
General::twominus = "f called with 1 argument, 2 arguments expected.";
f[_, _, x__] := Message[f::twoplus, "f", Length@{x} + 1]
f[x__] := Message[f::twominus, "f", Length@{x} + 1]


Define the function

f[x_, y_] := x + y + 1;


Call the function

f[1]
f::twominus: f called with 1 argument, 2 arguments expected.

f[1, 2]
4

f[1, 2, 3]
f::twoplus: f called with to much arguments, 2 argument expected.

-
Some things to consider: (1) Your messages have no placeholders; nothing is being filled in from the second and following arguments of Message. You can use merely Message[f::twominus] if you want the message printed verbatim. (2) You may wish to define the message for f rather than for General` unless you intend to use the same messages for other functions as well. – Mr.Wizard Apr 18 '13 at 9:26