1
$\begingroup$

While attempting to optimize my program, I noticed an issue with the Refresh expressions I am using inside a particular Dynamic[]. I will use a simplified example to illustrate the problem.

Suppose I have the following variables and InputFields:

clockVar = Dynamic[Round[Clock[5]]];
x = 1;
y = 1;

InputField[Dynamic[x]]
InputField[Dynamic[y]]

Now, suppose I create the following Dynamic plot:

Dynamic[
  Refresh[
    a = 2 * x;
    Print["a refreshed"];
  ,TrackedSymbols :> {x}
  ];

  Refresh[
    b = 2 * y;
    Print["b refreshed"];
 ,TrackedSymbols :> {y}
 ];

 Refresh[
   c = Setting[clockVar];
   Print["c refreshed"];
 ,UpdateInterval -> 1
 ];

 ListPlot[{{a, 0}, {0, b}, {c, c}}]
]

The first refresh block is meant to refresh its contents only when the value of x is changed, the second refresh block is meant to refresh its contents only when the value of y is changed, and the third refresh block is meant to refresh its contents every second.

However, when observing the output of the Print[] statements, it is clear that , instead, all three refresh blocks refresh every second (presumably because of the option UpdateInterval -> 1 in the third refresh block).

Further, if I get rid of the third Refresh block, that is:

Dynamic[
  Refresh[
    a = 2 * x;
    Print["a refreshed"];
  ,TrackedSymbols :> {x}
  ];

  Refresh[
    b = 2 * y;
    Print["b refreshed"];
 ,TrackedSymbols :> {y}
 ];

 ListPlot[{{a, 0}, {0, b}}]
]

then, if I change either x or y, both Refresh blocks refresh their contents.

I have spent a few hours now experimenting with different nesting of the Refresh statements, and have looked through the Refresh[] and Dynamic[] documentation, but I cannot seem to find a solution to this problem.

If someone with more knowledge about how Dynamic[] and Refresh[] work can explain the problem, and suggest ways to approach circumventing this problem, I would be greatly appreciative. In particular, I need a general solution, since the problematic Dynamic[] in my program involves complicated user-defined functions.

$\endgroup$
2
$\begingroup$

What eventually is 'refreshed' is the parent Dynamic, not only what is inside Refresh. Refresh tells outer Dynamic what to care about. And if there are many Refresh specifications then the outer Dynamic will care about all of that.

And at the end of the day the whole content of Dynamic is evaluated again. So each of Refresh/Print expressions as well. That is why you see print associated with y when only x changed. The same applies to updates caused by UpdateInterval.

If you want to 'track' separate changes you really need to have separate Dynamic/DynamicWrappers for them:

Row[{
  Dynamic @ ListPlot[{{a, 0}, {0, b}}],

  Dynamic[ a = 2 * x; Print["a refreshed"];"",             TrackedSymbols :> {x}],
  Dynamic[ b = 2 * y; Print["b refreshed"];"",             TrackedSymbols :> {y}],
  Dynamic[ c = Setting[clockVar]; Print["c refreshed"];"", UpdateInterval -> 1]
}]

Even better would be to trigger changes from the controller that changes x/y e.g.:

Slider @ Dynamic[x, (x = #; a = 2 x)& ]

Related topic:

What is the point of Refresh if Dynamic has an UpdateInterval option?

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.