# How can I work out which functions work with SetOptions?

Not all functions seem to work with SetOptions. e.g.

SetOptions[Grid, BaseStyle -> Directive[Red]];
Grid[{{"hello", "world"}}]

hello world


the font is not red.

SetOptions[Row, BaseStyle -> Directive[Red]];
Row[{"hello", "world"}]

hello world


...and the font is red.

SetOptions[InputField, FieldSize -> 5];
InputField[Dynamic[x]]


the input field size is much larger than 5. But on the other hand

InputField[Dynamic[x], Sequence @@ Options[InputField]]


yields an input field with field size 5.

...and so on.

What is the easiest way to work out (i.e. make a list of ...) which functions can't be used with SetOptions?

-
It'd also be interesting to know which objects work with it, e.g. it works with Graph, \$FrontEndSession, etc. but all these are somewhat special –  Szabolcs Jan 20 '12 at 9:16
Really good question! +1 –  Mr.Wizard Jan 20 '12 at 9:20

I don't know the direct answer to the specific question on SetOptions, but if we look at the purpose of (re)setting options globally, I have some alternative suggestion. A need to set options globally means that you need some persistent configuration of options which you'd like to be applied many times, without extra effort on your side. This can be achieved by creating such option(s) configuration and then always passing options locally (explicitly). It is possible to create helper functions / macros, which would automate this process for you and make it look and feel (almost) as if you have set your options globally.

I have implemented a simplistic options configuration manager, and a lexically scoped construct withOptionConfiguration, which can be wrapped around your code containing a function call of interest. One can also implement dynamically-scoped environments, for which the option-passing will happen also for all code called from the code within a construct. To my mind, this will save a lot of hassle even if / when you get the exhaustive answer to your direct question, since with the approach I suggest, you don't have at all to remember which functions work with SetOptions and which don't.

-
In a rare turn of events I shall not vote for your answer as I don't believe it addresses the question asked. (but I'll go find another answer of yours I haven't seen yet and vote for that to compensate) –  Mr.Wizard Jan 20 '12 at 17:01
@Mr.Wizard I wanted to make this a comment, but it was too large for that. I actually strongly dislike resetting options globally (SetOptions), particularly for system functions, but also generally. I think this practice should be officially discouraged, since it changes the global state of the system. As soon as their will be many interdependent third-party applications / packages in widespread use, (and I hope this will happen, for the sake of Mathematica community), the use of SetOptions will create nothing but problems. My personal view, of course. –  Leonid Shifrin Jan 20 '12 at 17:07
@Mr.Wizard You are right that this does not address the direct question, but I clearly stated so, and also I think it addresses the reason for this question. If I get lots of negative feedback on this from others, I may delete this answer and just incorporate this in the book. –  Leonid Shifrin Jan 20 '12 at 17:09
Please do not delete it; again I know (or at least presume) that you cannot see my votes, but I still feel the need to explain why I don't vote for an otherwise thoughtful answer. I do not share your blanket distaste for global options, because Mathematica is often an individually used and individualized software. I would however be concerned by packages that changed my options without notice! –  Mr.Wizard Jan 20 '12 at 17:17
@LeonidShifrin No, please don't delete. An answer is always useful if it adds anything of substance to solving/understanding the question. Sometimes (generally, not specific to this), such answers can also be helpful in figuring out the underlying problem or if it's a conceptual misunderstanding on the OP's part. Deleting should be reserved for answers that talk of football when the question is on tennis. I can understand people not wanting to vote, but that doesn't diminish the usefulness. –  The Toad Jan 20 '12 at 17:20

As noted in the question, when you set an option to a function which appears not to work with SetOptions the options do get set, e.g. from the question:

InputField[Dynamic[x], Sequence @@ Options[InputField]]


but for whatever reason the global setting does not get used locally by default.

Another interesting case is this:

SetOptions[Grid, Background -> RGBColor[1, 0, 0]]


which returns a list of Grid options with the new Background, yet when you do the same with GridBox

SetOptions[GridBox, Background -> RGBColor[1, 0, 0]]
SetOptions::nspt: "SetOptions of GridBox is not supported"


So testing the actual "box form" seems to highlight the problem. In this case GridBox is not supported for SetOptions even though Grid did not return an error. So the following solution is a variation of what was provided to me by tech support. Check can be used to return something in the case of a SetOptions error:

Check[SetOptions[GridBox, "a" -> "b"], err, SetOptions::nspt]

SetOptions::nspt: "SetOptions of GridBox is not supported."
err


First get a list of names:

names = Names["System*"]


test the names for the SetOptions error

list = Quiet[Map[Check[SetOptions[ToExpression[#], "a" -> "b"]; Null, #,
SetOptions::nspt] &, names]];


delete the Null elements

DeleteCases[list, Null]

DynamicModuleBox,DynamicWrapperBox,GridBox,InputFieldBox,ItemBox,Line3DBox,LineBox,
LocatorBox,LocatorPaneBox,OpenerBox,OptionValueBox,OverlayBox,PaneBox,PanelBox,
RectangleBox,RotationBox,SetterBox,Slider2DBox,SliderBox,TabViewBox,TemplateBox,
TogglerBox,TooltipBox,ValueBox}


So we have a list of 36 types of boxes that cannot be used with SetOptions.

-
Despite new answers bumping questions to the top I missed this until now. +1 (Also, consider accepting your own answer.) –  Mr.Wizard Feb 16 '12 at 12:49
is accepting your own answer good etiquette? –  Mike Honeychurch Feb 16 '12 at 20:57
95% of this answer came from tech support. Nevertheless it does seem to be the best way of finding this information so I am accepting "my own" answer. –  Mike Honeychurch Feb 16 '12 at 23:51
re "is accepting your own answer good etiquette?" if you want the consensus opinion of this specific community I suggest a question in Meta; mine is that is that it is perfectly fine if it is a proper answer and not simply something of the form: "I ended up using Joe's answer with this small tweak:" which I am sure you have seen before. In the case of an answer like this one could argue that it is bad etiquette to not accept your answer as then it doesn't show the problem as solved. –  Mr.Wizard Feb 17 '12 at 3:04
@Mr.Wizard and Mike Honeychurch: I've checked that this method miss Style(StyleBox) and Text(InterpretationBox). What lead me to the doubts if this is the core of the problem. For example: SetOptions[Style, FontColor -> Red]; Style["test"] will not work while you can SetOptions on StyleBox. It is getting weirder, try to set SetOptions[StyleBox, FontColor -> Red] (set it to Automatic to undo) and later SetOptions[StyleBox, FontSize -> 25] <- it seems that color was changed on all types of cells while size only for "InlineText", but basic "InlineText" cell have no StyleBox... –  Kuba Jul 18 '13 at 7:07

I think the reason for this is that many functions pass their options to other functions that they call during evaluation. See for example this answer to a related question on StackOverflow. So you can't set the option for the function you use, only the function that the option is passed to.

So for example, in one of my packages (you can guess which one, I have of course changed the initials of my employer to "XYZ") I have a function that starts with the definition:

XYZLineGraph[data:{{__?NumericQ} ..},
dates_List, opts:OptionsPattern[{XYZLineGraph,
DateListPlot, XYZDateTicks, XYZTickGrid, GraphNotesGrid}]] := (* more here *)


I cannot set the defaults for XYZLineGraph that are actually defaults of DateListPlot using SetOptions[XYZLineGraph].

An example:

test = FinancialData["AAPL", {2008}];
SetOptions[XYZLineGraph, BaseStyle -> Directive[Red]];
XYZLineGraph[test]  (* not red *)


SetOptions[DateListPlot, BaseStyle -> Directive[Red]];
XYZLineGraph[test]


(* still not red, because I set the relevant defaults separately *)

DateListPlot[test]  (* is red *)


As for identifying which functions can have SetOptions work this way, I suspect the only way you could do this for built-in functions would be a laborious use of Trace.

-
hmmm, I might email you about that @Verbeia. –  Mike Honeychurch Jan 20 '12 at 23:32
Don't tell me this question is about your implementation of the same functionality? That is funny. –  Verbeia Jan 21 '12 at 0:00
No completely unrelated actually but given your answer I thought I would chat to you about it. I am the only person that uses my computer and I like to set certain configurations for functions I use regularly. –  Mike Honeychurch Jan 21 '12 at 0:07
As you've shown, the issue is that BaseStyle is not an option of XYZLineGraph. However, you can make it one by including Options[DateListPlot] in the options for XYZLineGraph, using FilterRules to strip out any changes to the defaults you make. Then, using FilterRules, you pass the DateListPlot options to it from within XYZLineGraph`. –  rcollyer Jan 31 '12 at 4:21