4
$\begingroup$

This question already has an answer here:

I have function the needs to enable some Optional parameters and an OptionsPattern. The issue I am facing is that the options are being matched to the optional parameters when the optional parameters are excluded.

How do I specify that the optional parameters should use their default when not provided without making multiple function definitions.

With

ClearAll[f]
f[ts_, maxError_, fitAlgorithm_: LinearModelFit, algorithmParams_: {\[FormalX], \[FormalX]}, 
  opts : OptionsPattern[]] :=
 <|"fitAlgorithm" -> fitAlgorithm, "algorithmParams" -> algorithmParams, "opts" -> {opts}|>

Then all optional defaults and no options works.

f[1, 2]
<|"fitAlgorithm" -> LinearModelFit, "algorithmParams" -> {\[FormalX], \[FormalX]}, "opts" -> {}|>

However, any additional parameters are misinterpreted

f[1, 2, StepMonitor :> (a = # &)]
<|"fitAlgorithm" -> StepMonitor :> (a = #1 &), "algorithmParams" -> {\[FormalX], \[FormalX]}, "opts" -> {}|>

The StepMonitor option should be the first item in opts. Instead it is taken to be the fitAlgorithm parameter.

I know multiple function defintions will work. For example:

ClearAll[f]
f[ts_, maxError_, fitAlgorithm_, algorithmParams_, 
  opts : OptionsPattern[]] :=
 <|"fitAlgorithm" -> fitAlgorithm, "algorithmParams" -> algorithmParams, "opts" -> {opts}|>
f[ts_, maxError_, opts : OptionsPattern[]] := 
 f[ts, maxError, LinearModelFit, {\[FormalX], \[FormalX]}, opts]
f[ts_, maxError_, fitAlgorithm_, opts : OptionsPattern[]] := 
 f[ts, maxError, fitAlgorithm, {\[FormalX], \[FormalX]}, opts]

But this is not actually creating optional parameters with default values.

$\endgroup$

marked as duplicate by Kuba Dec 8 '17 at 21:06

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ Sorry for delay with closing ;) And of course let me know if you disagree. $\endgroup$ – Kuba Dec 8 '17 at 21:07
  • $\begingroup$ @Kuba Nope. You are on point. I searched for "OptionsPattern Optional" and that question does not appear in the resulting list. $\endgroup$ – Edmund Dec 8 '17 at 21:17
  • $\begingroup$ It is usually easier if you know the answer, here Except + OptionQ, but it should not work that way :) $\endgroup$ – Kuba Dec 8 '17 at 21:25
4
$\begingroup$

I think Except[_?OptionQ] can be a general way to go:

ClearAll[f]
f[ts_, maxError_
, fitAlgorithm : Except[_?OptionQ] : LinearModelFit
, algorithmParams : Except[_?OptionQ] : {\[FormalX], \[FormalX]}
, opts : OptionsPattern[]
] := <|
  "fitAlgorithm" -> fitAlgorithm
, "algorithmParams" -> algorithmParams
, "opts" -> {opts}
|>


f[1, 2, StepMonitor :> (a = # &)]

<|"fitAlgorithm" -> LinearModelFit, "algorithmParams" -> {[FormalX], [FormalX]}, "opts" -> {StepMonitor :> (a = #1 &)}|>

$\endgroup$
4
$\begingroup$

Instead of using just a default, also include a pattern. For example:

ClearAll[f]
Options[f] = {"a"->"b"};

f[
    ts_,
    maxError_,
    fitAlgorithm_Symbol:LinearModelFit,
    algorithmParams:{__Symbol}:{\[FormalX],\[FormalX]},
    opts:OptionsPattern[]
] := <|"fitAlgorithm"->fitAlgorithm,"algorithmParams"->algorithmParams,"opts"->{opts}|>

Then the following does what you want:

f[1, 2, "a"->"c"]
f[1, 2, {x, y}, "a"->"d"]
f[1, 2, fooFit, "a"->"e"]
f[1, 2, fooFit, {x, y}, "a"->"f"]

<|"fitAlgorithm" -> LinearModelFit, "algorithmParams" -> {\[FormalX], \[FormalX]}, "opts" -> {"a" -> "c"}|>

<|"fitAlgorithm" -> LinearModelFit, "algorithmParams" -> {x, y}, "opts" -> {"a" -> "d"}|>

<|"fitAlgorithm" -> fooFit, "algorithmParams" -> {\[FormalX], \[FormalX]}, "opts" -> {"a" -> "e"}|>

<|"fitAlgorithm" -> fooFit, "algorithmParams" -> {x, y}, "opts" -> {"a" -> "f"}|>

$\endgroup$

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