# Evaluating function only when its optional argument is numeric

I want to have the argument 'a' for myf2 in form of optional argument, but at the same time I need to evaluate the function only if 'a' is Numeric, see also my previous question.

Options[myf2] = {"a" -> 1};
myf2[b_?NumericQ, opts : OptionsPattern[]] := Module[{y, x, a},
a = OptionValue["a"];
If[NumericQ[a], First[y /.NDSolve[{a y'[x] == b y[x] Cos[x + y[x]], y[0] == 1},
y, {x, 0, 30}]][10]]
];

datamyf2 = {#, myf2[1, #] + 0.01 RandomReal[]}&/@Range[0.5, 1.5,0.1]

model = NonlinearModelFit[datamyf2, myf2[b, "a" -> a], b, a]


When I tried to add the NumericQ test for 'a' in myf2, the problem is that it returns Null upon evaluating with symbol 'y' {myf2[1, "a" -> y]}, instead of leaving it unevaluated at all (as for the case when 'a' was specified as regular argument with a_?NumericQ)

How can I than specify that it should have numeric value for 'a' in the option?

Thanks!

-
Is there a good reason why you want a to be an optional argument? At least in your example it doesn't look optional to me. –  sebhofer Aug 7 '13 at 9:43
I posted an example function, but in real application I'm using quite many optional arguments in a physical simulation function. In that case optional arguments are very handy, see i.e. (reference.wolfram.com/mathematica/tutorial/…) –  Cendo Aug 7 '13 at 9:53
I'm still not convinced by this approach. I would rather define different parameter sets (e.g. as lists of replacement rules) and pass these sets to the function. –  sebhofer Aug 7 '13 at 9:59
Thanks for the Accept! However, I always recommend that users wait 24-hours before selecting an answer so as to give everyone around the world a chance to reply before a question appears concluded. –  Mr.Wizard Aug 7 '13 at 10:25

This question appears to be about Options, not optional arguments. While it is true that OptionsPattern[] is a form of optional argument that is not typically how options themselves are described. Edit: I see that the tutorial refers to options as "named optional arguments" so I guess my understanding of convention was incorrect.

The meat of your question seems to be how to check an option value according to a pattern and return your expression (function call) unevaluated if it does not pass. You can do this with a Condition on the right-hand side of the definition:

Options[fn] = {"a" -> 1};

fn[b_?NumericQ, OptionsPattern[]] :=
stuff[OptionValue["a"], b] /; NumericQ @ OptionValue["a"]

fn[3.5]
fn[3.5, "a" -> 7]
fn[3.5, "a" -> y]

stuff[1, 3.5]

stuff[7, 3.5]

fn[3.5, "a" -> y]


Note that opts : was not needed here as OptionValue is being used rather than e.g. FilterRules.

You could also make use of sharing between a condition and function body for more complicated tests or simply to avoid having to use OptionValue["a"] twice. (See mid-way through Using a PatternTest versus a Condition for pattern matching for an explanation of this behavior.)

ClearAll[fn]

Options[fn] = {"a" -> 1};

fn[b_?NumericQ, OptionsPattern[]] :=
Module[{a = OptionValue["a"]}, stuff[a, b] /; NumericQ[a]]

fn[3.5]
fn[3.5, "a" -> 7]
fn[3.5, "a" -> y]

stuff[1, 3.5]

stuff[7, 3.5]

fn[3.5, "a" -> y]

-