The problem is that in chartOptions the variable chartData is a free variable referring to a global definition. In the BarChart expression, the chartData variable is localized to the containing module and is thus invisible to chartOptions Change chartOptions to accept chartData as a parameter: chartOptionschartData_, yName_, xName : and then adjust the BarChart expression accordingly: Module{chartData},chartData=RandomInteger20,20; BarChartchartData,chartOptionschartData, "yName","xName".
The problem is that in chartOptions the variable chartData is a free variable referring to a global definition. In the BarChart expression, the chartData variable is localized to the containing module and is thus invisible to chartOptions. Change chartOptions to accept chartData as a parameter: chartOptionschartData_, yName_, xName := ... and then adjust the BarChart expression accordingly: Module{chartData},chartData=RandomInteger20,20; BarChartchartData,chartOptionschartData, "yName","xName".
1, beat me to it by 3 - 4 seconds. – rcollyer Aug 25 at 15:33 2 @rcollyer It should help, yes. – Leonid Shifrin Aug 25 at 15:40 2 @rcollyer Using Block would indeed work since it temporarily changes the global definition of the symbol.
However, I would generally advise one to stick to parameters and local variables as much as possible to avoid subtle scoping problems -- like the one identified by this question. In the case of chartOptions, it is not immediately obvious to the reader that the function has a dependency upon a global definition. That lack of transparency often does (and did) lead to trouble.
– WReach Aug 25 at 15:43 1 I agree with removing the dependence on a global variable. It makes the code brittle, and easily exposed to changes. I was just trying to illustrate that alternatives do exist.
– rcollyer Aug 25 at 16:11 1 I also second @WReach in his advice to avoid global dependencies. This SO question stackoverflow. Com/questions/6236458/… is quite illustrative in that respect, and in my answer there I gave extended arguments and explanations of subtleties involved.
– Leonid Shifrin Aug 25 at 18:28.
Not a direct answer to the question (which has been answered already by @WReach), but I think that @500 touched on an important topic. We may often want to create something like a configuration containing certain custom option settings for several options. Changing options globally is IMO more often than not a bad idea (this is not to detract from the answer of @Verbeia.
There are certainly cases where global options resetting is appropriate. My suggestions should be viewed as complementary). Here I will reproduce an implementation of a very light-weight option-configuration manager to create persistent option configurations, that I wrote when answering a similar question on Mathgroup, and a relevant discussion.
Usage Let me start with the usage - the implementation for the option-configuration manager can be found at the bottom of my post. We will start with a test function with options: In54:= ClearAllbar; Optionsbar = {barA -> 1, barB -> 2}; barx__, OptionsPattern := Module{}, {"barA: " -> OptionValuebarA, "barB: " -> OptionValuebarB}; At first, we just call it without any explicitly passed options. It displays the values of options that it currently uses - in this case, those that are set globally through Options (OptionValue takes care of it): In57:= bar1, 2 Out57= {"barA: " -> 1, "barB: " -> 2} We now call one of the functions from our manager API (see below for the implementation): setOptionConfigurationbar,"first", {barA -> 11, barB -> 22, fooA -> 1}; This defines an option configuration for the function bar under name "first".
To make use of this option configuration, we use another function: withOptionConfiguration, like so: In58:= withOptionConfigurationbar1, 2, "first" Out58= {"barA: " -> 11, "barB: " -> 22} This looks as if we did change options for bar globally, but in fact we did not. Now, using our option configuration in the presence of explicitly passed option(s): In59:= withOptionConfigurationbar1,2,barA->"overriding_barA","first" Out59= {barA: ->overriding_barA,barB: ->22} In this setup, option configuartions override Optionsbar, but options explicitly passed to bar override both. One can also inspect the option configurations for a given function, by calling another function from our API: In60:= getOptionConfigurationbar,"first" Out60= {barA->11,barB->22} With this construct, one can do some cool things like creating shortcuts such as this: In61:= first=Functioncode,withOptionConfigurationcode,"first",HoldFirst; In62:= first@bar1,2,barA->"overriding_barA" Out62= {barA: ->overriding_barA,barB: ->22} In this way, one can create any number of option configurations one wants, and it is quite clear to anybody reading this code, what is going on.
Implementation ClearAllsetOptionConfiguration, getOptionConfiguration, withOptionConfiguration; SetAttributeswithOptionConfiguration, HoldFirst; Module{optionConfiguration}, optionConfiguration__ = {}; setOptionConfigurationf_, tag_, {opts___? OptionQ} := optionConfigurationftag = FilterRules{opts}, Optionsf; getOptionConfigurationf_, tag_ := optionConfigurationftag; withOptionConfigurationf_args___, tag_ := fargs, Sequence @@ optionConfigurationftag; ; Remarks On a few occasions, I found this type of constructs useful. Their main advantage is that while option configurations are persistent, they work by passing options locally, so options are not reset globally.
And global option resetting is a dangerous business, particularly for common (e.g. Built-in) functions, and when you deliver your functionality to others. Also, the above implementation is so light-weight that it can easily be extended or modified to suit one's needs.
I don`t feel comfortable yet to apply this. However I feel it actually address a situation I am experiencing while dealing with the tradeoff bet customization and automation if those are appropriate terms. Ok and definitely @Leonid gets cut.
Given how bad OS Lion is, I would think it is on them! – 500 Aug 25 at 22:35 Leonid, you might consider putting the code for custom functions at the bottom of your answers. I say this because I realized that I lost track of what you were saying after trying to understand the first code block in your post.
I think it would be more streamlined to show the usage first, then provide code for those who care. – Mr.Wizard Aug 26 at 7:06 @Mr.Wizard Thanks, good idea! Is it better now?
– Leonid Shifrin Aug 26 at 11:28.
Creating a function like this one is the right way to handle options that depend on the data to be plotted. But some of these options can be set for all uses of BarChart in that Mathematica session using SetOptions. For your example you might choose to define: SetOptionsBarChart, Frame -> {{True, True}, {True, True}}, ImageSize -> 300, ChartStyle -> Black, ChartElementFunction -> "FadingRectangle", LabelStyle -> DirectiveBlack, Bold, 18 And leave only the options that depend on the data in your chartOptions function.
EDIT - caveat I did this without a working copy of Mathematica nearby - typos might still remain If you do not want to set options globally, which as @Leonid pointed out, can result in other unwanted effects, you could define a custom function: myBarChartdata_List,yName_,xName_, opts:OptionsPattern{myBarChart,BarChart,RectangleChart,Graphics}:= BarChartdata,opts,FrameLabel -> {{yName, None}, {None, xName}}, FrameTicks -> {{{Round@Min@data, Round@(Max@data/2), Round@Max@data}, None}, PlotRange -> {Automatic, 1.3*Max@data}} And then define the options to that function: OptionsmyBarChart = {Frame -> True, ImageSize -> 300, ChartStyle -> Black, ChartElementFunction -> "FadingRectangle", LabelStyle -> DirectiveBlack, Bold, 18}; SetOptionsBarChart, Frame -> True, ImageSize -> 300, ChartStyle -> Black, ChartElementFunction -> "FadingRectangle", LabelStyle -> DirectiveBlack, Bold, 18 I should also point out that you could avoid the customised PlotRange option by setting it to All and setting the PlotRangePadding option as required. Probably PlotRangePadding->{{Automatic, Automatic},{Scaled0.23,0}}. Scaled gives the padding as a fraction of the plot dimensions.
Since you want the whitespace to be 0.3 of the full range of data, that is probably 0.3/1.3= 0.23, but you might want to experiment.
This will help a lot! – 500 Aug 25 at 21:38.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.