I haven't found an example where I can't get rid of Refresh[]:
In[1]:= Dynamic[DateString[],UpdateInterval->1]
Out[1]= Sat 10 Nov 2012 01:36:34
In[2]:= Dynamic[Refresh[DateString[],UpdateInterval->1]]
Out[2]= Sat 10 Nov 2012 01:36:34
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 insideDynamic
. You might almost wonder why its options are not simply options toDynamic
. But in fact it is often important to placeRefresh
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. IfRefresh
were wrapped around the whole expression insideDynamic
, 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.)
Refresh[DateList[]
to 100 Refresh[DateList[]
, then it would be different to 100 Dynamic[DateList[]
. The Dynamic
has to make sense as a visual piece of thing on the screen.
$\endgroup$
Print["check"]; showclock
in If
you can see that whole Dynamic
is evaluated, so UpdateInterval
setting from refresh is passed to outer Dynamic
. IMO this example sucks, using nested Dynamic
would be way better habit to learn because the If statement would be only checked when showclock is changed, not each .05 second
$\endgroup$
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
.
TrackedSymbol:>{f}
option for the Dynamic[Refresh[counter++,None];f[20]]
in such cases which seems to achieve the same behavior. Can you explain what the advantage of the Refresh
approach is? I find it somewhat problematic that the author of f
has to take care of a Dynamic
not refreshing which might make use of f
which he probably not even knows about when he originally wrote f
(hasn't that situation occured at WRI?). What is the overhead of such a Refresh
, would you recommend to generally use such Refresh
wrappers just in case of?
$\endgroup$
Commented
Oct 8, 2015 at 8:23
RepeatedTiming[Do[ Refresh[i^2, None], {i, 10^6}]][[1]]/RepeatedTiming[Do[ unfresh[i^2, None], {i, 10^6}]][[1]]
Maybe this explains the slowdown of 15-30% in pure kernel operations from Mathematica 9 to Mathematica 10 ?
$\endgroup$
Commented
Oct 8, 2015 at 8:54
f
available for your use by users. If I don't have end-to-end control, then I have to anticipate any usage. It's not reasonable for me to tell users to hack around my problems. That having been said, this certainly does not arise in many functions. Functions developed with no side effects (which is quite a lot of them) won't exhibit this behavior. For example, in 10.0.0, there was an infinite Dynamic
triggering bug in GeoGraphics
. The solution finding the accidental side effects and removing them, not Refresh
.
$\endgroup$
Commented
Oct 8, 2015 at 14:05
memoize
->myThemePlotWithHeavyComputation
and f
->tabPlotsFromMainTabView
, where the former is the Kernel function that, what was my concern too, doesn't have to be wrapped in Refresh
"just in case". However the latter is specific package symbol related to package GUI where Refresh
makes sense, it would be there because of specific reason, not just in case.
$\endgroup$
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.
Dynamic
s. I have, many times, reported bugs to developers around the company for which the fix is to wrap their code in Refresh[#, None]&
. Such a change has no effect outside of Dynamic
, but exactly the desired effect inside Dynamic
.
$\endgroup$
Commented
Oct 7, 2015 at 17:07
Dynamic
evaluates to a thing with head Dynamic
. Refresh
evaluates to its contents. If you are implementing a function which can be used anywhere, but which must not trigger any enclosing Dynamic
unnecessarily, the only way to do this is Refresh
. It is literally impossible to do this with Dynamic
. Consider, for example, a function which memoizes its results. Inside of a Dynamic
, such a function triggers twice because the act of memoization produces a global side effect in the symbol table which will retrigger enclosing Dynamic
s. Refresh
can stop that dead.
$\endgroup$
Commented
Oct 8, 2015 at 7:24
I agree with Rojo's comments under his answer and I'd upvote them but the example from tutorials given in his answer is more confusing than educational for me (as expressed in comments). "For me", not "in my opinion" so maybe one can learn more from this part of tutorial.
Nevertheless, I want to show you examples were using Refresh
really matters.
Refresh
gives not head to expr
which may be very useful (see comments under accepted answer)
Dynamic[{DateString[], 2 Refresh[2, UpdateInterval -> 1]}]
Refresh
matters when you have a Dynamic
which isn't standard Dynamic
that is going to be converted to DynamicBox
, I know two exceptions:
First is usage Dynamic
inside user interface elements like Sliders
. This was pointed out by Fred Simons here.
So only the first example gives expected result of updating controller:
Slider[Dynamic[Refresh[RandomReal[], UpdateInterval -> 1]]]
Slider[Dynamic[RandomReal[], UpdateInterval -> 1]]
Second is (FrontEnd|Notebook|Cell)DynamicExpression
. If you try to do this without Refresh
, with Dynamics
only, you will probably fail:
DynamicModule[{x = 0},
Dynamic[{DateString[], x}]
,
Initialization :> ( SetOptions[EvaluationCell[],
CellDynamicExpression :> Refresh[x++,
UpdateInterval -> 1, TrackedSymbols :> {}]
]
)]