1

I have several variables in my DynamicModule and some parts of my computation depend only on subset of them. I am trying to use Refresh to "cache" values but can't make it work.

Example of the problem:

verySlowFunction[x_] := Module[{}, Print["SLOW"]; x * x];

DynamicModule[
 {a = 1, b = 1},
 Dynamic[
  Module[
   { x = Refresh[verySlowFunction[a], TrackedSymbols :> {a}] },
   Column[{
     Slider[Dynamic[a]],
     Slider[Dynamic[b]],
     {a, b , x + x + b} 
     }]]]]

I expect "SLOW" to be printed only when I drag "a" slider, but it is printed when I'm dragging "b" slider as well.

I know that Dynamic clones whole expression tree on its evaluation, that's why x is always different, but this one doesn't work as well:

Module[
 {x},
 DynamicModule[
  {a = 1, b = 1},
  Dynamic[
    x = Refresh[verySlowFunction[a], TrackedSymbols :> {a}] ;
   Column[{
     Slider[Dynamic[a]],
     Slider[Dynamic[b]],
     {a, b , x + x + b} 
     }]]]]
mikea
  • 379
  • 1
  • 5

2 Answers2

2

Try this one

DynamicModule[{a = 1, b = 1, x = 1}, 
 Column@{Slider@Dynamic[a, (a = #; x = verySlowFunction[a]) &], 
   Slider@Dynamic[b], Dynamic@{a, b, x + x + b}}]

The second argument in Dynamic is evaluated when the corresponding variable changes.

Or this one

DynamicModule[{a = 1, b = 1}, 
 Column@{Slider@Dynamic[a], Slider@Dynamic[b], Dynamic@{a, b}, 
   Dynamic[x = verySlowFunction[a]]}]

You can manually insert Refresh with TrackedSymbols in the last Dynamic.

ybeltukov
  • 43,673
  • 5
  • 108
  • 212
  • 1
    Thanks, this will work. However in my actual case verySlowFunction depends on more than one argument, and there are several temporary calculations to perform. This would require me to duplicate re-evaluation into lots of controls, right? – mikea Sep 14 '13 at 00:43
  • @mikea There are more elegant approach if you have several arguments. See update. – ybeltukov Sep 14 '13 at 00:53
  • The second version has some serious omission: it does not include calculations based on x. That's what causes me troubles. – mikea Sep 14 '13 at 05:50
1

That's tricky question, I have to admit I do not have general solution but I usually do what is good for particular case. Here I'd use DynamicWrapper:

verySlowFunction[x_] := Module[{}, Print["SLOW"]; x*x];

DynamicModule[{a = 1, b = 1},
              DynamicWrapper[
                     Column@{
                             Slider@Dynamic[a],
                             Slider@Dynamic[b],
                             Dynamic@{a, b, x + x + b}},
                     x = verySlowFunction[a];]]

This is not the answer to the question how to use Refresh for your purposes but I think it is not bad approach :). I'm looking forward for more answers how one can deal with this.

About link provided by @Gustavo, imo there is to much acrobatics in there which is not necessary in case of DynamicModule. DynamicModule != Manipulate because the body of DM is not automatically updated when variables are.

I appreciate any comments if I'm mistaken somewhere.

Kuba
  • 136,707
  • 13
  • 279
  • 740