I like to avoid talking about implementation where the implementation shouldn't
be relevant to the design and behavior (even though it sometimes is due to
bugs). Too much pontification starts to sound like documentation and/or
information necessary for understanding the system, and it's really not. And in
this case, the discussion would be so long and involved that I'd probably lose a
whole day just writing it, and hear the sound of the foreheads of 2,000
MathGroup subscribers smack their keyboards as they fall asleep in boredom.
But in answer to your question below about the workarounds...if these
workarounds work for you, they will probably work for everyone else, too. I
endorse the ones we've already covered as being things which do not contradict
the existing design, which successfully work around the bug as I presently
understand it (I have not fully explored the issue yet, but I will eventually),
and which will not be intentionally broken in future implementations.
Sincerely,
John Fultz
jfultz at wolfram.com
User Interface Group
Wolfram Research, Inc.
On Tue, 25 May 2010 18:58:03 +0200, Istv=E1n Zachar wrote:
> Dear All,
>
> thanks for the workaround suggestions, and thanks for the clarification
> of the issue, John. I (and others as well, I'm pretty sure) would
> definitely want to know more about the internal mechanisms of the
> dynamic interface, but I understand that this would perhaps be too much
> for the present forum. As far as I understand, every call *other* than
> Dynamic[pr] (like Dynamic[pr+0], Dynamic[FullForm[pr]], Dynamic[f[pr]],
> etc.) should work in such queer situations. I haven't tested it
> extensively, so I ask whether we can rely on this trick?
>
> Istvan
>
>
> On 2010.05.25. 18:29, John Fultz wrote:
>> On Thu, 20 May 2010 06:40:08 -0400 (EDT), Albert Retey wrote:
>>
>>> Hi,
>>>
>>>
>>>> Alas, can not answer your questions properly, but the following
>>>> modification
>>>> of your code
>>>> seems to also work fine:
>>>>
>>>> DynamicModule[{range ==== {0, 100}, sw ==== False},
>>>> Module[{pr ==== 0},
>>>> Grid@{{
>>>> Button["Push me",
>>>> (sw ==== True;
>>>> Do[pr ==== i; Pause[.02];, {i, range[[1]], range[[2]]}];
>>>> sw ==== False;), Method -> "Queued"],
>>>> Dynamic@ProgressIndicator[pr, range],
>>>> Dynamic@pr,
>>>> Dynamic@Switch[sw,
>>>> True, "Calculating...",
>>>> False, "Finished.",
>>>> _, "Standing by."]}}]]
>>>>
>>>> The issue seems to be with the<pr> variable. My guess is that by
>>>> localizing<pr> with DynamicModule vs plain Module or not
>>>> localizing at
>>>> all,
>>>> you somehow indicate to Dynamic that<pr> is going to change due to
>>>> Dynamic
>>>> updating, so Dynamic does not track its possible changes by other
>>>> means
>>>> (like by explicit assignments in a loop that you have). My guess is
>>>> supported by observing that once you localize with DynamicModule,
>>>>
>>>> 1. Dynamic@ProgressIndicator[pr, range], works while
>>>> ProgressIndicator[Dynamic[pr], range] does not
>>>>
>>>> 2. Consider the following modification:
>>>>
>>>> ClearAll[f];
>>>> DynamicModule[{pr ==== 0, range ==== {0, 100}, sw ==== False},
>>>> Grid@{{
>>>> Button["Push me",
>>>> (sw ==== True;
>>>> Do[pr ==== i; Pause[.02];, {i, range[[1]], range[[2]]}];
>>>> sw ==== False;), Method -> "Queued"],
>>>> Dynamic@ProgressIndicator[pr, range],
>>>> Dynamic[f[pr]],
>>>> Dynamic@Switch[sw,
>>>> True, "Calculating...",
>>>> False, "Finished.",
>>>> _, "Standing by."]}}]
>>>>
>>>> You will observe that now the value of<pr> inside<f> is being
>>>> properly
>>>> updated inside Dynamic during the run of your code. In particular,
>>>> by
>>>> using
>>>> f[x_]:====x, you can get back the desired result - you can even
>>>> localize
>>>> <f>
>>>> as well as put this definition inside the same DynamicModule
>>>> (although
>>>> this
>>>> is certainly a hack). In both cases, we replaced Dynamic[pr] with
>>>> something
>>>> else, which apparently made Dynamic properly update the output. Of
>>>> course,
>>>> my observations at best somewhat clarify "how", but not "why" -
>>>> hopefully
>>>> others will have more to say here.
>>>>
>>>>
>>> Well, I think it's up to someone from WRI to comment, in my opinion it
>>> is certainly a bug, and one that I think I have seen in other cases,
>>> but
>>> never was able to track down to something this simple. Here I have
>>> some
>>> examples which look very inconsistent to me:
>>>
>>> DynamicModule[{range == {0, 100}, sw == False, pr == 0},
>>> Grid[{{
>>> Button["Push me", (
>>> sw == True;
>>> Do[pr == i; Pause[.02];, {i, range[[1]], range[[2]]}];
>>> sw ==== False;
>>> ),
>>> Method -> "Queued"
>>> ],
>>> Column[{
>>> ProgressIndicator[Dynamic[pr], range, ImageSize -> 100],
>>> ProgressIndicator[Dynamic[pr, TrackedSymbols :> {pr}], range,
>>> ImageSize -> 100],
>>> Dynamic[ProgressIndicator[pr, range, ImageSize -> 100]],
>>> ProgressIndicator[Dynamic[pr + 0], range, ImageSize -> 100]
>>> }],
>>> Column[{
>>> Dynamic[pr, TrackedSymbols :> {pr}],
>>> Dynamic[0 + pr],
>>> Dynamic[pr]
>>> }]
>>> }}]
>>> ]
>>>
>>> If you first look at the second column you will find that just
>>> Dynamic[pr] behaves differently than Dynamic[0+pr], not exactly
>>> something one would expect. At least you can help Mathematica to still
>>> do what you want by using the TrackedSymbols options for Dynamic[pr].
>>>
>>> Considering that, it is not so surprising that
>>> ProgressIndicator[Dynamic[pr]] does not work, but now you can't even
>>> make it work with neither the TrackedSymbols-Option nor the pr+0 trick
>>> -- even more inconsistency. The case Dynamic[ProgressIndicator[pr]]
>>> seems then to be like the Dynamic[0+pr] case and probably works for
>>> the
>>> same reasons...
>>>
>>> Are these bugs? Will they be corrected in future versions?
>>>
>>> When dealing with these issues I would also love to see functionality
>>> which would allow to have some insight in or even control the
>>> dependency
>>> tree that Mathematica uses to decide whether it has to update a
>>> Dynamic
>>> or not. The concept of Dynamic evaluation to create graphical user
>>> interface really is an interesting idea and has charm and advantages.
>>> But when it is not working reliable, I find it to take more effort
>>> (usually searching for tricks and workarounds) to create nontrivial
>>> interfaces than when using the standard concepts (MVC,Observer,...) in
>>> other languages. There I have to create the dependencies myself, but
>>> at
>>> least I have full control over them...
>>>
>>> hth,
>>>
>>> albert
>>>
>> This is a thread I normally would have commented on promptly, but life
>> and work
>> sometimes stand in the way of such promptness.
>>
>> To be clear, this is absolutely a bug. The code provided by the
>> original poster
>> was correct (not optimal, but definitely correct) in every way. All of
>> the
>> usages in Albert's response should also have worked.
>>
>> Put very simply, there are some cases where a Dynamic reference to a
>> DynamicModule variable does not properly update in real time as it's
>> being
>> changed by a button press. A similar issue would probably arise from
>> ActionMenu
>> choices, which act much like button presses (although I haven't
>> actually tried
>> it). I could give more exhaustive information about why some things
>> oddly seem
>> to work such as Dynamic[0+pr], but that would require a technical
>> explanation of
>> the system to a greater depth than should be necessary for
>> understanding how to
>> use it for even advanced uses.
>>
>> As Albert suggests, the original user could work around these problems
>> by making
>> the following replacements in his code...
>>
>> Dynamic@ProgressIndicator[Dynamic@pr, range] ->
>> Dynamic[ProgressIndicator[pr, range]]
>>
>> Dynamic@pr -> Dynamic[pr + 0]
>>
>> Speaking to Albert's final points...I wonder, Albert, what you're
>> looking for in
>> terms of controlling the dependency tree that the TrackedSymbols option
>> doesn't
>> offer? But I do appreciate your wanting a better tool for
>> understanding when or
>> why Dynamics fire. I am sometimes reduced to iterative testing with
>> various
>> values of TrackedSymbols to understand which symbol in a complex bit of
>> code is
>> triggering unwanted Dynamic refreshes. It doesn't seem crazy to
>> imagine a tool
>> which could do this for you.
>>
>> Sincerely,
>>
>> John Fultz
>> jfultz at wolfram.com
>> User Interface Group
>> Wolfram Research, Inc.