Problem using OptionValue with functions defined by SubValues, and the use of Options for function dispatch
I have a function that looks like:
(a : pump[_, __])["curve QH", opts : OptionsPattern[]] :=
Plot[x, {x, 0, 2}, Frame -> True, FrameLabel -> {"a", "b"},
Evaluate[FilterRules[{opts}, Options[Plot]]]
This code allows me to substitute the option of Plot
, with whatever I may want (where pump
acts like a very simple object).
Now suppose I want to use an option to define if a Plot
or a Table
should be outputed.
I imagined something like this:
(a : pump[_, __])["curve QH", opts : OptionsPattern["type" -> "plot"]] :=
Which[
OptionValue["type"] == "plot",
Plot[x, {x, 0, 2}, Frame -> True, FrameLabel -> {"a", "b"},
Evaluate[FilterRules[{opts}, Options[Plot]]]],
OptionValue["type"] == "table",
Table[x, {x, 0, 2, 0.1}]
]
but it doesn't work.
What is the best strategy to use Options with this kind of definition?
Answer
There are two problems I see with this code. The first one, and the one which gives you immediate problem you reported, is that, as it looks, short (magical) form of OptionValue
does not work with SubValues
- based definitions. So, you should replace
OptionValue["type"]
with
OptionValue[{opts}, "type"]
Or, if you wish to associate the option with pump
directly and use it within the SubValue
, you need to use
OptionValue[pump, {opts}, "type"]
instead.
The second, "conceptual" problem, is that you are really trying to use options for function dispatch, but in doing this your way, you give up the powerful rule-based function dispatch mechanism that is naturally available in mma. This is what I would do instead:
ClearAll[pump, dispatch];
(a : pump[_, __])["curve QH", opts : OptionsPattern["type" -> "plot"]] :=
dispatch[pump, OptionValue[{opts}, "type"]][a, "curve QH", opts];
dispatch[pump, "plot"][_, _, opts : OptionsPattern[]] :=
Plot[x, {x, 0, 2}, Frame -> True, FrameLabel -> {"a", "b"},
Evaluate[FilterRules[{opts}, Options[Plot]]]];
dispatch[pump, "table"][_, _, opts : OptionsPattern[]] :=
Table[x, {x, 0, 2, 0.1}]
I delegated the dispatch to a new (extra) symbol dispatch
, introduced specifically for this purpose. This looks cleaner and more extensible to me than using Which
statement.
EDIT
Addressing the issue raised in comments: note that, as another manifestation of OptionValue
- OptionsPattern
magic being lost for SubValues
- based functions, the above solution, as written, will not provide the intended default behavior, when the "type"
option is not explicitly given. To make that work, one can do:
(a : pump[_, __])["curve QH", opts : OptionsPattern["type" -> "plot"]] :=
dispatch[
pump,
OptionValue[{opts,"type" -> "plot"}, "type"]
][a, "curve QH", opts];
adding the default option explicitly in OptionValue
.
Comments
Post a Comment