5
$\begingroup$

I've been trying to learn more about DynamicModule (I do not use them, as I used Manipulate all the time).

After some time struggling with this, and reading everything I can about Dynamics, and lots of trials and errors, I gave up.

Any one can figure why this DynamicModule will initialize correctly and run ok, ONLY after I hit ENTER on the cell an extra time?

This is a problem, since when I saved it to a CDF and opened the CDF, it does not run, since it needs an ENTER to initialize, which is not possible to do in CDF.

DynamicModule[{max = Pi/4, plot = plotClass[Pi/4]},

 Row[{
   Dynamic[plot@set[max]],
   Framed@Grid[{
      {Slider[Dynamic[max], {.1, 2 Pi, .1}], Dynamic@max},
      {Dynamic[plot@make[]], SpanFromLeft}
      }
     ]
   }
  ],
 Initialization :> {
   plotClass[$max_] := Module[{self, mymax},
     self@set[v_] := mymax = v; 
     self@make[] := Module[{x},
       Plot[Sin[x], {x, 0, mymax}, PlotRange -> {{0, 2 Pi}, {-1, 1}}, 
        ImageSize -> 200]
       ];
     mymax = $max;
     self
     ]
   }
 ]

Mathematica graphics

To see the problem, simply do

  1. Paste the above into an empty cell (but do not hit ENTER yet)
  2. close the kernel Evalution->Quit kernel
  3. Hit ENTER on the cell. Now you'll see the plot
  4. Now move the slider. You'll see that the plot does not update
  5. Now hit ENTER one more time into the cell. Now moving the slider will update the plot
  6. To reproduce, delete the output cell and go back to step 2.

So it needs one more ENTER to work. Another way to see this, is to save the notebook as CDF and open the CDF. You'll see it does not work.

I am sure I am doing something silly. But as I said, I just started learning DynamicModule.

The problem is with the evaluation with the Module in the Initialization section. It does not get defined without an extra ENTER for some reason. I tried many different way to define this Module, and they are failed. One extra ENTER is needed.

Mathematica 9.0.1, on windows 7.

$\endgroup$

2 Answers 2

8
$\begingroup$

I think that Mike has a point: it is always good to start with something simple. Here is a very simple example which shows the main problem you have: the Initialization-code is evaluated only after the body of the DynamicModule has been evaluated. This might be surprising considering its name but I think is in agreement with the documentation, which is somewhat vague about these details:

DynamicModule[{x = (Print[Date[] -> "local vars"]; Pause[0.1]; 0.5)},
 Print[Date[] -> "body"]; Pause[0.1];
 Row[{Slider[Dynamic[x]], Dynamic[x]}],
 Initialization :> (Print[Date[] -> "initialization"]; Pause[0.1])
 ]

There is another problem with your construct that you have to take into account: When the output is still visible and you Quit the Kernel the Initialization-code of that still visible DynamicModule might be evaluated before anything of the shift-return-evaluation that will create the new output. This will in your case define plotClass, so that the new output will work from the beginning, but only if the old output was still visible (that is neither deleted nor scrolled out of sight). In combination the outcome will look almost random. To prevent this, it is better to define plot=plotClass[max] also in the Initialization-code: it's probably important to note that you do have access to the local variables of the DynamicModule there as well. This will also ensure that this definition is made when the DynamicModule is initialized without the shift-return-evaluation that did generate it...

Finally I think there is an additional potential source of errors in your code: with Dynamic[plot@set[max]] you are setting a variable from within a Dynamic evaluation. My experience is that with this you are asking for trouble as it is not defined whether this Dynamic will be evaluated before the one that will show the plot. Either way you might trigger additional (unneccessary) evaluations which might become a performance problem and in more complicated cases even create infinite recursions, hangups and crashes. It is much better to do all settings of variables in the second argument of the controler Dynamic, as here:

DynamicModule[{max = Pi/4., plot},
 Row[{
   Dynamic[NumberForm[N[plot@getMax[]], {4, 2}]],
   Framed@Grid[{{
       Slider[
        Dynamic[max, (max = #; plot@setMax[max]) &], {.1, 2 Pi, .1}], 
       Dynamic[NumberForm[N@max, {4, 2}]]
       }, {
       Dynamic[plot@make[]], SpanFromLeft
       }}]
   }],
 Initialization :> (
   plotClass[$max_] := Module[{self, mymax},
         self@setMax[v_] := mymax = v;
         self@getMax[] := mymax;
         self@make[] := Module[{x},
           Plot[Sin[x], {x, 0, mymax},
            PlotRange -> {{0, 2 Pi}, {-1, 1}}, ImageSize -> 200]
           ];
         mymax = $max;
     self
     ];
   plot = plotClass[max];
   )
 ]
$\endgroup$
2
  • $\begingroup$ @nasser How about this sentence: When DynamicModule is first evaluated, initial assignments for local variables are made during the evaluation. Any setting for the Initialization option is evaluated only when the output of DynamicModule is displayed. So, as the docs already stated earlier, variables are localized and initialized, the body is evaluated. It will be displayed after that. That's when the Initialization code will execute. $\endgroup$ Feb 24, 2013 at 13:03
  • $\begingroup$ @Nasser: I just have seen your comments -- and believe that Sjoerd has clarified most of what remained unclear. About the names of the local variables: I think that there are indeed two names generated for plot: During the kernel-evaluation plot will be localized, with a naming like plot$9944. Then when it is displayed, the FrontEnd takes over the control about variables local to DynamicModule and plot gets yet another name, something like FE'plot$$137. I don't think that this means you are using a global variable anywhere, though. $\endgroup$ Feb 24, 2013 at 16:22
3
$\begingroup$

This is too long for a comment. I don't really have time to pull this code apart but if the objective is to learn DynamicModule wouldn't a simpler piece of code be a better start?

If you look at what variables have been created after the first ENTER this is a small sample of what you get

enter image description here

I think it would be best to pull your code apart and figure out why you are infinitely looping through variable creation.


Just extending my comment...

I was about to go to bed so didn't have time to figure it out last night. Nice answer from Albert. To get a feel for what happens after the first Shift+Enter wrap the thing in InputForm. What gave me a headache last night and led me to leave it was this:

This is what you get from Alberts code above

DynamicModule[{max = 0.7853981633974483, plot}, 
 Row[{Dynamic[NumberForm[N[plot[getMax[]]], {4, 2}]], 
   Framed[Grid[{{Slider[Dynamic[max, (max = #1; plot[setMax[max]]) & ], 
        {0.1, 2*Pi, 0.1}], Dynamic[NumberForm[N[max], {4, 2}]]}, 
      {Dynamic[plot[make[]]], SpanFromLeft}}]]}], 
 Initialization :> (plotClass[$max_] := Module[{self, mymax}, 
     self[setMax[v_]] := mymax = v; self[getMax[]] := mymax; 
      self[make[]] := Plot[Sin[x], {x, 0, mymax}, PlotRange -> {{0, 2*Pi}, {-1, 1}}, 
        ImageSize -> 200]; mymax = $max; self]; plot = plotClass[max]; ), 
 DynamicModuleValues :> {}]

However last night when I did that with your code I got:

DynamicModule[{max = Pi/4, plot = plotClass[Pi/4]}, 
 Row[{Dynamic[plot[set[max]]], 
   Framed[Grid[{{Slider[Dynamic[BoxForm`RemapVariable[max, {0.1, 2*Pi, 0.1}], 
         BoxForm`RemapValue[#1, max, {0.1, 2*Pi, 0.1}] & ], {0., 61.83185307179586, 
         1.}], Dynamic[max]}, {Dynamic[plot[make[]]], SpanFromLeft}}]]}], 
 Initialization :> {plotClass[$max_] := Module[{self, mymax}, 
     self[set[v_]] := mymax = v; self[make[]] := Module[{x}, 
        Plot[Sin[x], {x, 0, mymax}, PlotRange -> {{0, 2*Pi}, {-1, 1}}, 
         ImageSize -> 200]]; mymax = $max; self]}, DynamicModuleValues :> {}]

...which was a WTF! moment because I have not come across BoxForm`RemapVariable before. Has anyone else ever seen that before?

$\endgroup$
2
  • $\begingroup$ I saw RemapValue once, this is the link. But I don't know anything about it. $\endgroup$
    – Szabolcs
    Feb 24, 2013 at 22:16
  • $\begingroup$ @Mike See my edit on how to put a backtick in inline code. This backtick notation isn't the luckiest for mma ... but then is there any character mma doesn't use? $\endgroup$
    – Szabolcs
    Feb 24, 2013 at 22:17

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.