Re: A Dynamic mess
- To: mathgroup at smc.vnet.net
- Subject: [mg92962] Re: [mg92925] A Dynamic mess
- From: John Fultz <jfultz at wolfram.com>
- Date: Tue, 21 Oct 2008 01:43:52 -0400 (EDT)
- Reply-to: jfultz at wolfram.com
On Mon, 20 Oct 2008 07:32:31 -0400 (EDT), chandler.seth at gmail.com wrote: > There has just got to be an easier way to do the following. The > example is somewhat silly, but if I could understand how to do this > competently, I would learn a lot. > > Suppose I want to compute the sum of an integer (z) and a value > chosen from some uniform distribution on the interval 0 to a. I want > to do this interactively and I do NOT want the draw from the random > distribution to change when I change z, just when I change the > parameter a. So, we create the number z as follows: > > z=6;SetterBar[Dynamic[z],{6,7,8}] > > If I do the following, it does not work as expected because, I > suppose, Dynamic[z] is a FrontEnd object in its heart of hearts (a > DynamicBox) and thus does not add to 2 the way an integer would. Correct. The thing to keep in mind is that Dynamic[z] evaluates to Dynamic[z]. If you do... Dynamic[z]//InputForm you'll see that. In StandardForm, it displays as something else, in precisely the same way that a/b looks like "a/b" in InputForm, but displays as something else (i.e. a FractionBox) in StandardForm. Any further evaluations are a side effect of that display, and not a principal effect of evaluating Dynamic[]. > > Dynamic[z]+2 > > So, this can be fixed with Dynamic[z+2] > > OK, now instead of adding 2, let's add some random value > > a=0.5;Slider[Dynamic[a]]; > > Dynamic[z+RandomReal[{0,Setting@Dynamic[a]}]] (* setting is added > because if one just uses Dynamic[a] one is referencing a front end > object rather than an actual number*) Are you hoping that the internal Dynamic will somehow freeze the RandomReal[] unless 'a' has been explicitly changed? This won't happen for two reasons. One is that an outer Dynamic reevaluates its contents entirely, including inner Dynamics, whenever it's triggered (as it will be by the change in 'z'). But the more important reason is that the inner Dynamic doesn't actually have any Dynamic functionality. Observe... In[12]:= Setting[Dynamic[a]] // InputForm Out[12]//InputForm= 0.5 Recall that I said that Dynamic[] evaluates to itself. But Setting of Dynamic[] evaluates not to a dynamic result, but to the contents of the Dynamic. So your statement is effectively the same as... Dynamic[z + RandomReal[{0, a}]] Keep reading for the solution... > This evaluates, but it does not have the desired behavior. Now, when I > change z I also get a new draw from the random distribution. I thought > of trying to blocking the redraw by wrapping Dynamic around the > RandomReal, like this. > > Dynamic[z+Dynamic@RandomReal[{0,Setting@Dynamic[a]}]] > > But that doesn't work at all. It still redraws when I change z and the > addition no longer works in the desired way since the Dynamic > expression is not "really" a number but just a box. > > I can solve the latter problem by wrapping a Setting in front of the > Dynamic > > Dynamic[z + Setting@Dynamic[RandomReal[{0, Setting@Dynamic[a]}]]] > > Now it adds properly but it still refreshes the random draw every time > I change z. > > This doesn't work either and the expression is getting awfully > complicated > > Dynamic[z + > Refresh[Setting@Dynamic[RandomReal[{0, Setting@Dynamic[a]}]], > TrackedSymbols -> {a}]] > > And this doesn't work either > > Dynamic[Setting@Dynamic[z] + > Setting@Dynamic[RandomReal[{0, Setting@Dynamic[a]}]]] > > Can someone help! Yes. Many evaluation ordering issues with Dynamic can be solved using With[], including this one. Here's my code that does what you want... Dynamic[With[{draw = RandomReal[{0, a}]}, Dynamic[z + draw]]] Some important points here. Note that both Dynamics actually display. The outer Dynamic will obviously display the result of With[], and the result of With[] is another Dynamic[]. If I had hidden the inner Dynamic behind a semicolon or Setting, this would not have worked. So, in the front end, this is represented as two nested DynamicBox objects. The outer Dynamic will trigger anytime 'a' is changed, and will reevaluate its contents entirely, including the inner Dynamic. The inner Dynamic will only change if 'z' has changed, and its reevaluation will never cascade into a reevaluation of the outer Dynamic. In summary, Setting[] won't help you with the kind of problems you're having, but you'll find With[] very useful. In my Mathematica programs, I almost never used With[] until Dynamic[] came along, at which point I found it an invaluable tool for controlling precisely how things will evaluate. Sincerely, John Fultz jfultz at wolfram.com User Interface Group Wolfram Research, Inc.