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

Let me know if this is not enough, but I'll just quote the docs for now

From the Advanced Dynamic Functionality tutorial:

Nesting Refresh

In the "Refresh" section examples, Refresh is always the outermost function inside Dynamic. You might almost wonder why its options are not simply options to Dynamic. But in fact it is often important to place Refresh as deeply in the expression as possible, especially if it specifies a time-based updating interval.

Consider this example.

DynamicModule[{showclock = True}, {Checkbox[Dynamic[showclock]], 
  Dynamic[If[showclock, Refresh[DateList[], UpdateInterval -> 0.05], 
    "No clock"]]}]

When the checkbox is checked, Refresh is causing frequent updating of the clock, and CPU time is being consumed to keep things up-to-date. When the checkbox is unchecked, however, the Refresh expression is no longer reached by evaluation, the output remains static, and no CPU time is consumed. If Refresh were wrapped around the whole expression inside Dynamic, CPU time would be consumed constantly, even if the clock were not being displayed. The words "No clock" would be constantly refreshed, pointlessly. (This refreshing is not visible; there is no flicker of the screen, but CPU time is being consumed nevertheless.)


I really think that other answers here are adequate, but since specific examples are being requested, here's one.

f[x_] := memoize[x]
memoize[x_]:=memoize[x]=x

This is a function you want to call inside and outside of Dynamic. You want the caching effect, but you don't want Dynamic to go crazy on this. Which it will. Observe:

In[139]:= Clear[memoize];
f[x_] := memoize[x]
memoize[x_]:=memoize[x]=x
counter=0;
Dynamic[Refresh[counter++,None];f[20]]
Dynamic[counter]

Out[142]= 20 (* the on-screen representation of memoize[20] *)
Out[143]= 2 (* the on-screen representation of counter *)

I'm using counter here as an indication of how many times the memoize Dynamic resolves itself.

So, this Dynamic evaluated twice. Rather ironic given that I was actually trying to save computational power by memoizing. But we're not done, yet. Evaluate:

f[40]

Note counter just ticked again. And, no, putting Dynamic inside of the definition of f does not work. Because we don't want f to produce a Dynamic. We want a value, not a Dynamic. So, delete your previous outputs (else they'll continue to trigger and contaminate the experiment) and redefine f as:

f[x_] := Refresh[memoize[x], None]

Problem solved. I write real-world functions which create caches in this way. I do not want them triggering wildly inside of Dynamic.


Refresh also has a TrackedSymbols option. Consider the case where several dynamic variables are declared in the first argument to DynamicModule but you only want updating to occur on a proper subset of those variables. An example is given at the bottom of the answer I gave to this question.