From: Leonid Shifrin on
Hi Leo,

For one thing, DeleteDuplicates is not strictly necessary since only the
first rule with the same l.h.s. applies.

More generally, though, creating a wrapper only to redefine some options
seems a bit of an overkill. Logically, someone who sees <foo> in your code
(may be yourself a few weeks later) will not easily see the connection to
<bar>. If you have several functions, and for each you would like several
option configurations to pick from, I'd create something like an option
configuration manager - something like this:

ClearAll[setOptionConfiguration, getOptionConfiguration,
withOptionConfiguration];
SetAttributes[withOptionConfiguration, HoldFirst];
Module[{optionConfiguration},
optionConfiguration[_][_] = {};
setOptionConfiguration[f_, tag_, {opts___?OptionQ}] :=
optionConfiguration[f][tag] = FilterRules[{opts}, Options[f]];
getOptionConfiguration[f_, tag_] := optionConfiguration[f][tag];
withOptionConfiguration[f_[args___], tag_] :=
f[args, Sequence @@ optionConfiguration[f][tag]];
];

Now, here is how you could use it:

ClearAll[bar];
Options[bar] = {barA -> 1, barB -> 2};
setOptionConfiguration[bar,
"first", {barA -> 11, barB -> 22, fooA -> 1}];
bar[x__, OptionsPattern[]] :=
Module[{},
Print["barA: ", OptionValue[barA]];
Print["barB: ", OptionValue[barB]]];

bar[1, 2]

barA: 1

barB: 2

withOptionConfiguration[bar[1, 2], "first"]

barA: 11

barB: 22

withOptionConfiguration[bar[1, 2, barA -> "overriding_barA"], "first"]

barA: overriding_barA

barB: 22

With this construct, you can do some cool things like creating shortcuts
such as this:

first =
Function[code, withOptionConfiguration[code, "first"], HoldFirst];

first(a)bar[1, 2, barA -> "overriding_barA"]

During evaluation of In[876]:= barA: overriding_barA

During evaluation of In[876]:= barB: 22


In this way, you can create any number of option configurations you want,
and it is quite clear to anybody reading this code, what is going on. Also,
you avoid the need of double - override such as your explicit options passed
to <foo>: in this setup, your configuartions override Options[bar], but
options explicitly passed to <bar> override both. IMO, this construct is
simpler.

Hope this helps.

Regards,
Leonid



On Sat, Mar 20, 2010 at 12:45 AM, Leo Alekseyev <dnquark(a)gmail.com> wrote:

> Suppose I have a function foo which is a wrapper for bar. Both of
> them have certain default options. Options[foo] includes some options
> that should be passed to bar, which may override some of bar's
> defaults, but if they are not provided bar should always receive some
> default options.
>
> Here are the definitions
>
> ClearAll[foo];
> ClearAll[bar];
> Options[bar] = {barA -> 1, barB -> 2};
> Options[foo] = {barA -> 11, barB -> 22, fooA -> 1};
>
> And here is the desired output:
> In[199]:= foo[] (* pass some default options to bar *)
> Out[199]= bar[{barA -> 11, barB -> 22}]
>
> In[200]:= foo[barA -> "overriding_barA"] (* overriding the default
> option barA *)
> Out[200]= bar[{barA -> "overriding_barA", barB -> 22}]
>
> This situation commonly arises for me, and I've been using the
> following implementation for foo[], which basically concatenates
> supplied and default options and deletes duplicates, but I keep
> thinking that there should be a better way. Is there?.. Am I missing
> something obvious here?..
>
> foo[opts : OptionsPattern[]] :=
> Module[{},
> bar[FilterRules[{opts}, Options[bar]]~Join~
> FilterRules[Options[foo], Options[bar]] //
> DeleteDuplicates[#, First[#1] == First[#2] &] &]]
>
>