# How to test if optional argument has been given?

I understand that the last call (f[1]) returns True because arg does not exist and thus SameQ tests a single argument ("ArgValue") which always returns True. Therefore no comparison can be done here at all. Now it is not possible to use ValueQ either, as arg does not exist, and thus it has no value so ValueQ[arg] would evaluate to ValueQ[]. How to test whether arg exists or not? I am aware that I can define another signature for just one argument (f[first_] := ...), but I want to solve it inside the function, if it is possible.

ClearAll[f];
f[first_, arg___] := (arg === "ArgValue");
{f[1, "ArgValue"], f[1, "NonArgValue"], f[1]}


{True, False, True}

UPDATE

In general, I want to test whether any optional argument was passed to f. Since f is in reality a quite large function with a lot of optional arguments and occasionally called with a quite complex argument structure, I decided that I do not want to create complex patterns for each case (i.e. a different signature). Insted I check inside f whether any extra argument was passed or not - which in tha baseline case means that there should be no extra argument. Thus f shouldn't return False in reality for only one argument (i.e. it still should perform some computation on its single argument), this is only for testing purposes here. A more realistic function would look like this:

ClearAll[func];
func[first_, arg___?overcomplicatedArgumentStructureQ] := Module[{...},
(* heavy computation *)
If[argExistQ[arg], (* do this *), (* do that *)];
(* some more heavy computation *)
];

• Based on your update, I think my recommendation of {} =!= {arg} is correct. You are testing the argument on the LHS already, using a test function. Leonid's {arg} === {"ArgValue"} doesn't make sense in this case, and it also assumes a specific value for the optional argument. Mar 19, 2012 at 13:12
• Leonid's answer is correct in the sense that if there is no arg given to f, it evaluates to False, else it also checks whether the given argument equals a certain value. While your solution works as well, I still prefer Leonid's way, as it does the test on the rhs and does not touch the lhs of the function definition (which I implicitly wanted). Mar 19, 2012 at 15:12
• @Mr.Wizard I did mention the comparison of {} and {arg} as a general suggestion as well, in my answer. Mar 20, 2012 at 0:07
• @Leonid In no way did I mean to disparage your answer. I simply found all of this confusing. If you find any additional value in my answer feel free to include it in yours. If you choose to do this I will delete it; otherwise I will leave it. Mar 20, 2012 at 0:28
• @Mr.Wizard Thanks, but in this case I'd keep things as they are, because we clearly interpreted the problem differently. I happenned to pick the interpretation that apparently was what Istvan was after, but IMO your answer is (as always) valuable. I did not vote for it this time though, since I think it solves a slightly different problem, but it does not mean that I find no value in it. Some people may come to this question having exactly the problem which your answer addresses and mine doesn't. Mar 20, 2012 at 0:35

Why not use something like

f[first_, arg___] := {arg} === {"ArgValue"};


For general tests, you can compare {arg} to {}, to determine whether or not the arg is empty.

• I was going to suggest the same, +1. Another possibility is default arguments. Mar 16, 2012 at 18:17
• @Szabolcs Thanks. I thought about default args as well, but did not include them, since that would make things a bit more complex and can possibly create some corner cases which one has to keep in mind. Mar 16, 2012 at 18:18
• @Szabolcs: it won't work with default arguments, just change my code to: f[first_, arg___ : Automatic] := (arg === "ArgValue"), which fails the same way at f[1]. Mar 16, 2012 at 18:23
• @István It will, but you must use arg__ : Automatic, not arg___ : Automatic Mar 16, 2012 at 18:26
• @Istvan When no argument is at all given, the optional part of the pattern comes into play, and effectively binds arg to Automatic, so in such case you effectively test Automatic==="ArgValue", which returns False. Mar 19, 2012 at 10:45

This question and Leonid's interpretation of it don't make sense to me.

This definition:

f[first_, arg___] := (arg === "ArgValue")


Will give True for f[1, "ArgValue", "ArgValue"] while Leonid's method will not.

Perhaps you want:

ClearAll[f]
f[first_, arg : "ArgValue" ...] := {} =!= {arg}

{f[1], f[1, "ArgValue", "ArgValue"]}

{False, True}


Without seeing your application I can only guess what you are trying to accomplish. Why are you trying to avoid creating a second definition? If you want f[1] to return False isn't

f[_] = False


the cleanest way?

• Yes, it is a good question why @István used arg___ and not arg_. If the aim is to allow either one or none at all, an optional argument with a default value is better. @István, can you clarify? Mar 17, 2012 at 14:38
• @Szabolcs and if you don't like Default you could use something like: arg : RepeatedNull["ArgValue", 1] Mar 17, 2012 at 14:42
• @Szabolcs, Mr.Wizard: I will try to make it more clear tomorrow, no time today. Mar 17, 2012 at 19:27
• @Mr.Wizard: I have added some clarifications to my question, hope it helps. The problem that Leonid's answer solves is that specific case (all other cases are handled in proper ways) when arg does not exist inside f but I still want to test its existence (but not its exact value, thus SameQ is somewhat unnecessary for the case). Mar 19, 2012 at 10:46