4
$\begingroup$

How can I set an absolute option for a user-defined function? I understand I can define options like this:

Options[myfit]={Method->t};
myfit[ data_, OptionsPattern[] ] := Fit[{1,t,OptionsValue[Method]},t];

but what if want Method to take only two possible options "Linear" and "Quadratic"?

Note that absolute options for built-in functions popup automatically for the user. So, I am trying to find the right syntax so that the pre-defined alternatives for the option popup like they do for builtin functions.

$\endgroup$
5
$\begingroup$

this works to restrict the options.

ClearAll[myfit]
Options[myfit] = {Method -> "default"};
myfit[data_, OptionsPattern[]] := 
 Module[{}, Print["accepted:", OptionValue[Method]]; ] /; 
  MemberQ[{"Linear", "Quadratic", "default"}, OptionValue[Method]]
myfit[0, Method -> "Linear"] (*accepted:Linear*)
myfit[0, Method -> "Quadratic"] (*accepted:Quadratic*)
myfit[0, Method -> "other"] (* *)
myfit[0] (*accepted:default*)

no idea on the auto completion..

$\endgroup$
1
$\begingroup$

Try this (for V10 because of Nothing, replace with ## &[] in previous versions)

Options[myfit] = {Method -> "Linear"};
myfit[data_, OptionsPattern[]] :=
 With[{mtd = OptionValue[Method]},
  Fit[data, {1, t, If[mtd == "Quadratic", t^2, Nothing]}, t]
   /; mtd === "Linear" || mtd === "Quadratic"
  ]

myfit[Range[10] + RandomReal[.1, {10}], Method -> "Linear"]

myfit[Range[10]^2 + RandomReal[.1, {10}], Method -> "Quadratic"]

myfit[Range[10]^3 + RandomReal[.1, {10}], Method -> "Cubic"]

0.0236243 + 1.00392 t

0.0845429 - 0.0195709 t + 1.00179 t^2

myfit[{1.08831, 8.09556, 27.0505, 64.0677, 125.062, 216.009, 343.037, 512.015, 729., 1000.06}, Method -> "Cubic"]

$\endgroup$
0
$\begingroup$

You can remove the option value checking from your function's body by testing the option values in the pattern match of the function call. This method allows your function's body to leave out testing for valid options which will simplify the code; which is very handy as function complexity increases.

ClearAll[myfit];
Options[myfit] = {Method -> "Linear"};

myfit[data_, opts : OptionsPattern[]] /;
  MemberQ[
    {"Linear", "Quadratic"},
    Method /. FilterRules[Append[{opts}, Options[myfit]], Method]
 ] :=
  Switch[OptionValue[Method], "Linear", t, "Quadratic", t^2]

then

myfit[{1}]
(* t *)

myfit[{1}, Method -> "Quadratic"]
(* t^2 *)

myfit[{1}, Method -> "Cubic"]
(* myfit[{1}, Method -> "Cubic"] *)

The MemberQ checks if the Method option is valid. The defaults are Appended to the provided options (opts) because the particular option may not have been provided and we need success in that case. FilterRules picks out rules with matching keys. Since provided options come before the defaults in the list of filtered rules ReplaceAll (/.) will pick the provided option instead of the appended default in the case an option is provided. Finally, MemberQ test if the option value is a member of the allowed list.

To test more than one option multiple MemberQ's can be Anded together in the pattern test.

Hope this helps.


Extension

Create a checkOptionValue function for multiple option checks.

ClearAll[checkOptionValue];
SetAttributes[checkOptionValue, HoldAll];

checkOptionValue[f_Symbol, opt_, optValues_List, opts : OptionsPattern[]] :=
 MemberQ[optValues, opt /. FilterRules[Append[{opts}, Options[f]], opt]]

Then use for multiple option checks.

ClearAll[myfit];
Options[myfit] = {Method -> "Linear", Background -> Green};

myfit[data_, opts : OptionsPattern[]] /;
  checkOptionValue[myfit, Method, {"Linear", "Quadratic"}, opts] &&
   checkOptionValue[myfit, Background, {Green, Purple}, opts] :=
 Panel[Switch[OptionValue[Method], "Linear", t, "Quadratic", t^2],
  Background -> OptionValue[Background]]

Which gives

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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