Re: Dynamic changing of variables
- To: mathgroup at smc.vnet.net
- Subject: [mg96365] Re: [mg96314] Dynamic changing of variables
- From: John Fultz <jfultz at wolfram.com>
- Date: Thu, 12 Feb 2009 06:37:57 -0500 (EST)
- Reply-to: jfultz at wolfram.com
A note to anybody who makes non-trivial Dynamic interfaces. Read the question and my response and understand it thoroughly. This is a really important
question and understanding the answer will help you to create very sophisticated and powerful Dynamic interfaces with no need for guesses or trial and error.
The error here is in the statement...
> In order to update "a" with the actual value of Sin[b] I need
> Dynamic around it. Unfortunately, now the variable "a" is invisibly
or, more specifically, what the definition of "it" is (take the oblique
reference to a U.S. presidential quote as you will). Yes, you do need to
introduce a Dynamic to get a=Sin[b] to evaluate, but putting it on the
right-hand side of the assignment is wrong in this context. The key is to
remember that Dynamic does not control anything about evaluation directly. What it does is to create a spot on the screen which has evaluation properties.
If, for example, you were to evaluate the following in a fresh Mathematica
session...
b=5;
Dynamic[a=b];
b=6;
Print[a];
...then what will be printed? Instead of evaluating it immediately, think about
it before you try it. Hint...it's a trick question, but understanding the trick
will open your mind to exactly what Dynamic is doing.
The answer, which I will not reveal here (because you should really try it for
yourself!) can be explained by the fact that the Dynamic never did anything
because it never showed up onscreen. The semicolon inhibited the onscreen
appearance of Dynamic, and without appearing onscreen, the evaluation of Dynamic
accomplishes nothing.
More subtly, if you remove all of the semicolons, the Print[] statement (at
least on my machine) *still* remains unchanged, but now for a completely
different reason. That's because the onscreen placement of a Dynamic guarantees
that its contents will be evaluated, but not *when* they'll be evaluated. My
example sets up a race condition which, at least on my machine in v7, the
Shift+Enter evaluation wins.
If I understand the intent of your example correctly, the place to begin is
here...
DynamicModule[{a, b = 0}, Dynamic[a = Sin[b];
Column[{Dynamic[a], Slider[Dynamic[b], {0, 2*Pi}]}]]]
I.e., wrap the Dynamic around the entire CompoundExpression including the
assignment and the Column.
You say this is a toy example that represents a real-world one. I believe
that...I've written things that look like your toy example many times. It's a
shame I'm not seeing your real example, though, because there are some further
simplifications and improved efficiencies which I might be able to comment on.
For example, in this case it's a bit wasteful that the Column[] is inside of a
Dynamic[]. It could be a static element which contains individual Dynamic
elements. Something like...
DynamicModule[{a, b = 0},
Column[{Dynamic[a = Sin[b]; a], Slider[Dynamic[b], {0, 2*Pi}]}]]
which is obviously silly in this example, but may point to something interesting
in your real-world code. Perhaps a generalization I could remark on is the
notion of an onscreen Dynamic which has no visual appearance. Something like
this...
DynamicModule[{a, b = 0}, Row[{Dynamic[a = Sin[b]; Spacer[0]],
Column[{Dynamic[a], Slider[Dynamic[b], {0, 2*Pi}]}]}]]
This is a more sophisticated technique in which Row[] is used to show a Dynamic
which takes essentially no onscreen space, and yet has an onscreen presence. In
this version, the Row[] and Column[] are static elements which are never
regenerated by Dynamic. And we can now more tightly confine the evaluation
behaviors of the elements of the Column so that they are regenerated on an
as-needed basis, rather than every time any variable in the whole interface
changes.
I recommend re-reading the Advanced Dynamic Functionality tutorial (or reading
it if you haven't already) in light of some of the things I've said here.
Especially the subsections "Automatic Updates of Dynamic Objects" and "Nesting
Dynamic". You can find it by typing tutorial/AdvancedDynamicFunctionality in
your help window.
Sincerely,
John Fultz
jfultz at wolfram.com
User Interface Group
Wolfram Research, Inc.
On Wed, 11 Feb 2009 05:22:24 -0500 (EST), Patrick Scheibe wrote:
> Hi,
>
> assume the following code lines:
>
> DynamicModule[{a, b 0},
> a = Dynamic[Sin[b]];
> Column[{
> Dynamic[a],
> Slider[Dynamic[b], {0, 2*Pi}]
> }]
> ]
>
> In order to update "a" with the actual value of Sin[b] I need
> Dynamic around it. Unfortunately, now the variable "a" is invisibly
> wrapped and completely useless for further calculations. I'm not able to
> calculate even a+1 inside the DynamicModule.
>
> DynamicModule[{a, b = 0},
> a = Dynamic[Sin[b]];
> Column[{
> Dynamic[a+1],
> Slider[Dynamic[b], {0, 2*Pi}]
> }]
> ]
>
> If I'm not just too stupid and this behaviour is intended, then I'm
> wondering whether this doesn't lead to problems when you have more
> complex constructs with several dynamic variables.
>
> Cheers
> Patrick
>
> PS: I was just pointed by another person on this and I found a way
> around it. So cannot provide a real problem I'm having. Nevertheless, I
> would be glad to know what you think since I couldn't really find the
> point in the documentation where this is explained.
- Follow-Ups:
- Re: Re: Dynamic changing of variables
- From: Patrick Scheibe <pscheibe@trm.uni-leipzig.de>
- Re: Re: Dynamic changing of variables