Re: What is the point of having Initializations in DynamicModule and Manipulate?
- To: mathgroup at smc.vnet.net
- Subject: [mg123095] Re: What is the point of having Initializations in DynamicModule and Manipulate?
- From: John Fultz <jfultz at wolfram.com>
- Date: Wed, 23 Nov 2011 07:06:16 -0500 (EST)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- Reply-to: jfultz at wolfram.com
On Tue, 22 Nov 2011 20:52:15 +0100, Fred Simons wrote: > With much interest I follow this discussion. In particular I want to > thank John Fultz for his clear explanation on why DynamicModule behaves > as it does. > > For me, a little question still open: what exactly happens when the > intialization option is evaluated? The rhs of the Initialization option, as it was formulated by MakeBoxes and delivered to the front end, is sent by the front end to the kernel. Normally, I wouldn't bother making this distinction...I would just tell people to always use RuleDelayed because using Rule is never what you want...but I'll entertain your question as an academic discussion about how evaluation works without advocating people actually copy anything you do here in code they actually want to use. > In the examples so far it is used as > a delayed rule, so the rule will be applied first and then evaluation > takes place. But evaluation of what? The important thing to remember is that there are two sorts of things happening, and you should never conflate the two. The kernel *evaluates* its result, then *typesets* it for the front end. If you want to deeply understand how Dynamic and DynamicModule works, you need to understand this distinction, as well as the various other things I've laid out. So, an initial question you should be asking yourself which would help to understand some of the issues you raise is, what happened in evaluation...i.e., what expression was actually passed to MakeBoxes for typesetting? This is really easy to figure out, actually. Just wrap InputForm around the input, and you'll see exactly what evaluation did. For example, I think using InputForm is pretty instructive in an example like this: In[1]:= DynamicModule[{a=7,b,c},b=5;Dynamic[a,b],Initialization:>(c=3)]//InputForm Out[1]//InputForm= DynamicModule[{a = 7, b = 5, c}, Dynamic[a, 5], Initialization :> (c = 3), DynamicModuleValues :> {}] InputForm shows you that the b=5 evaluated and changed the DynamicModule initialization...but the c=3 did not. Okay...preface finished...now onto your specific questions. > Anyway the side effect is that, in > the last example of Mike, a value is assigned to g, but too late to be > displayed in the dynamic module, and even in the output for g itself > when it was asked for in the same cell: > > In[1]:= Clear[g]; DynamicModule[{},g,Initialization:>{g="hello world"}] > g > Out[1]= g > Out[2]= g > > However, when we give these two commands in two input cells, the second > output now shows the value of g instead of the name g: > > In[3]:= Clear[g]; DynamicModule[{},g,Initialization:>{g="hello world"}] > Out[3]= g > > In[4]:= g > Out[4]= hello world > > This is something I think I understand. But the following is less clear > to me. For the initialization we will use now the immediate rule. Then > the result is what Mike is expecting: > > In[5]:= Clear[g]; DynamicModule[{},g,Initialization->{g="hello world"}] > Out[5]= hello world So, the question is, how did DynamicModule evaluate? This is easy to figure out. Although DynamicModule is HoldAll, virtually all functions in Mathematica evaluate their options regardless of the HoldAll status (in this case, DynamicModule is HoldAll because of the need to hold its first two arguments). I'm not aware of any exceptions to that rule (maybe somebody else knows something I don't). And Rule immediately evaluates its rhs...that is the one thing which distinguishes it from RuleDelayed. So, we might surmise that, during evaluation, the following bit: Initialization->{g="hello world"} might evaluate to Initialization->{"hello world"} with the side effect of having set g. And, in fact, InputForm confirms that: In[5]:= Clear[g]; DynamicModule[{}, g, Initialization -> {g = "hello world"}] // InputForm Out[5]//InputForm= DynamicModule[{}, "hello world", Initialization :> {"hello world"}, DynamicModuleValues :> {}] When this DynamicModule typesets, it doesn't hold {g="hello world"} in its Initialization...merely {"hello world"}. And you've now created a DynamicModule with an Initialization which is not going to work in future kernel sessions, so it's not very useful. This is exactly why I would say that it's best merely to always avoid Rule in the Initialization option. > When the frontend asks for evaluation of the intialization only when it > is displaying the dynamic module, it is still too late for using the > value for g, just as with the delayed rule, and we would have seen the > name g in the output. So my feeling is that the right hand side of the > immediate initalization is evaluated already during the shift-enter > evaluation. The following modification seems to confirm this, and raises > more questions: > > In[6]:= Clear[g]; > DynamicModule[{},Print[13];g,Initialization->{Print[12];g="hello world"}] > During evaluation of In[6]:= 12 > During evaluation of In[6]:= 12 > During evaluation of In[6]:= 12 > During evaluation of In[6]:= 12 > During evaluation of In[6]:= 13 > Out[6]= hello world > > The number 12 is printed even four times (see the recent question of > David Park on how often initialization is done) and only after that we > see the effect of the print statement in the argument of the dynamic > module, resulting in the display of the value of g. As I mentioned earlier, DynamicModule is HoldAll. Which means that even its options are held initially, but evaluated and processed in the internal implementation of DynamicModule. What you're seeing here isn't specific to the Initialization option...it happens with every option (even invalid ones), too. In an ideal world, that processing would only trigger a single evaluation of its options. My guess is that allowing the options to be evaluated multiple times allowed the implementation of DynamicModule to be much simpler. I think I would stipulate this as a minor bug, but probably so minor that it would never affect any real-world code. > Any comment is highly appreciated. > > Fred Simons > Eindhoven University of Technology Sincerely, John Fultz jfultz at wolfram.com User Interface Group Wolfram Research, Inc.