7
$\begingroup$

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!

$\endgroup$
4
  • 1
    $\begingroup$ 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. $\endgroup$
    – sebhofer
    Commented Aug 7, 2013 at 9:43
  • $\begingroup$ 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/…) $\endgroup$
    – Cendo
    Commented Aug 7, 2013 at 9:53
  • $\begingroup$ 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. $\endgroup$
    – sebhofer
    Commented Aug 7, 2013 at 9:59
  • $\begingroup$ 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. $\endgroup$
    – Mr.Wizard
    Commented Aug 7, 2013 at 10:25

1 Answer 1

8
$\begingroup$

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]
$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.