[Date Index]
[Thread Index]
[Author Index]
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.
Prev by Date:
**Re: Mathematica 6.0.0 on Suse 11.0**
Next by Date:
**Re: Speeding up a list construction**
Previous by thread:
**A Dynamic mess**
Next by thread:
**Re: A Dynamic mess**
| |