25
$\begingroup$

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
$\endgroup$
0

4 Answers 4

18
$\begingroup$

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.)

$\endgroup$
5
  • $\begingroup$ So what's the difference and why just not use Dynamic instead of Refresh? $\endgroup$
    – Kuba
    Nov 6, 2014 at 13:27
  • 1
    $\begingroup$ @Kuba They are VERY different. Refresh evaluates to nothing, it's just a marker that means "if you get to evaluate this snippet when updating the dynamic, then remember these are the update settings I want". Dynamic is something that doesn't evaluate at all, and it means "if this is going to be displayed in the front end, evaluate the contents before showing trying to reevaluate every time the user is looking at it and the result would change" $\endgroup$
    – Rojo
    Nov 6, 2014 at 16:24
  • 1
    $\begingroup$ But where's the difference if in the example above you replace Refresh with Dynamic? I know Refresh alone has no point but why to nest Refresh if you just may nest Dynamics? God, sometimes I think I should switch to cycling. $\endgroup$
    – Kuba
    Nov 6, 2014 at 16:51
  • $\begingroup$ @Kuba, its a case where you won't see a visual difference but its just a special case. It's not just that Refresh alone has no point. Its that Refresh doesn't affect calculations, its more like a tag, while Dynamic isn't evaluated. For example, if you changed 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$
    – Rojo
    Nov 6, 2014 at 17:36
  • 3
    $\begingroup$ I'm back! If you put 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$
    – Kuba
    Mar 30, 2015 at 11:19
14
$\begingroup$

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.

$\endgroup$
12
  • 4
    $\begingroup$ I have used an explicit 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$ Oct 8, 2015 at 8:23
  • 3
    $\begingroup$ @AlbertRetey the overhead is about 25%. Check: 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$ Oct 8, 2015 at 8:54
  • 1
    $\begingroup$ @AlbertRetey, I'm talking about a situation where a developer is making 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$
    – John Fultz
    Oct 8, 2015 at 14:05
  • 1
    $\begingroup$ @JohnFultz Thank's for the clarification. Though I am still confused as to why a kernel-only function should ever worry about the FrontEnd. I just do not use this design pattern and still can use kernel memoization just fine. $\endgroup$ Oct 8, 2015 at 14:28
  • 1
    $\begingroup$ @AlbertRetey I think I got this example and if so better names would help future readers. Like: 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$
    – Kuba
    Oct 19, 2015 at 7:23
11
$\begingroup$

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.

$\endgroup$
4
  • 4
    $\begingroup$ This is an underrated answer. We do this all the time in Mathematica code. If you have any function which modifies any non-localized symbol for any reason, this is the only way to prevent it from non-stop tickling parent Dynamics. 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$
    – John Fultz
    Oct 7, 2015 at 17:07
  • $\begingroup$ @JohnFultz can't arguee with you but I'm still missing some kind of convincing example. The one provided by Rojo is not such, as I stated in comments. I mean, I havent't seen examples of Refresh that couldn't be simply replaced with Dynamic (not counting non standard usage as in my answer). Moreover, Dynamic reduces amount of reevaluated content. Could you provide such example? $\endgroup$
    – Kuba
    Oct 8, 2015 at 7:11
  • 1
    $\begingroup$ @Kuba 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 Dynamics. Refresh can stop that dead. $\endgroup$
    – John Fultz
    Oct 8, 2015 at 7:24
  • $\begingroup$ @JohnFultz I know the Head issue, but I haven't seen any example that has Refresh as a really neat solution to it. I was always able to get what I need with nested Dynamic + TrackedSymbols and I felt like I have better control this way. However, memoization example is a good one! I'd love to see an answer with such but not simple enough that one could workaround it with injecting / evaluating this function outside dynamics and put there under new name or something. $\endgroup$
    – Kuba
    Oct 8, 2015 at 7:35
8
$\begingroup$

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.

  1. Refresh gives not head to expr which may be very useful (see comments under accepted answer)

     Dynamic[{DateString[], 2 Refresh[2, UpdateInterval -> 1]}]
    
  2. 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 :> {}]
       ]
      )]
      
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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