7
$\begingroup$

If a notebook containing

a = {1, 2};
Dynamic[a[[2]]]
(* 2 *)

is executed, closed, and then opened in a new session, it yields

enter image description here

along with the expected error message,

Part::partd: Part specification a[[2]] is longer than depth of object. >>

Instead, I would like Dynamic not to change the answer from the previous session until the notebook is first executed again. Thereafter, in the new session it should behave as it normally would. How can this be accomplished programmatically? An answer that involves executing a = {1, 2} is not useful, because it does not generalize to my actual problem, in which Dynamic yields lengthy invalid results, unless the entire preceding portion of the notebook has executed.

Addendum

My thanks to Mike Honeychurch for reminding me to include several variants I had tried that also do not meet my goal.

DynamicModule[{}, Dynamic[a[[2]]]]

If[a[[1]] > 0, DynamicModule[{}, Dynamic[a[[2]]]]]

DynamicModule[{}, If[a[[1]] > 0, Dynamic[a[[2]]]]]

DynamicModule[{}, Dynamic[Refresh[a[[2]], TrackedSymbols -> {a}]]]
$\endgroup$
11
  • $\begingroup$ The way to avoid this is 1) to use DynamicModule so that you localise your variables to the notebook -- in your example the variable is global so requires kernel evaluation; 2) test the variable in some way and only display if True. $\endgroup$ Feb 1, 2016 at 6:50
  • $\begingroup$ @MikeHoneychurch Thank you for your suggestions. I was remiss in failing to point out that I had already tried both without success. $\endgroup$
    – bbgodfrey
    Feb 1, 2016 at 13:52
  • 3
    $\begingroup$ Dynamic[If[ValueQ[a], a[[2]], {}]] gives {} instead of error, is that good enough? $\endgroup$ Feb 1, 2016 at 15:18
  • 2
    $\begingroup$ How about DynamicModule[{}, Dynamic@a[[2]], SaveDefinitions -> True] $\endgroup$ Feb 1, 2016 at 20:16
  • 1
    $\begingroup$ @SimonWoods Your version is the best. Please post it as an answer. $\endgroup$ Feb 1, 2016 at 20:23

3 Answers 3

6
$\begingroup$

You can use the SaveDefinitions option of DynamicModule for this:

DynamicModule[{}, Dynamic@a[[2]], SaveDefinitions -> True]
$\endgroup$
3
  • $\begingroup$ Your solution meets the needs of my actual calculation. Thanks. Interestingly, in the simple problem in the question, your DynamicModule line of code above gives a values that can be used outside the DynamicModule. $\endgroup$
    – bbgodfrey
    Feb 2, 2016 at 2:06
  • $\begingroup$ @bbgodfrey keep in mind that each module will store a and all subsequent definitions separately so if you are not careful the size of the notebook may increase a lot. With simple cases this is very nice solution. $\endgroup$
    – Kuba
    Feb 2, 2016 at 7:46
  • $\begingroup$ @bbgodfrey, SaveDefinitions adds the definition a = {1, 2} to the Initialization option of the DynamicModule (add //ToBoxes to the end of my code to see this). This code gets run when the dynamic stuff is first displayed, so it is just as if you evaluated a = {1, 2} in the normal way. $\endgroup$ Feb 2, 2016 at 9:35
3
$\begingroup$

To start your notebook with Dynamic Updating Enabled not being checked add this code to your notebook:

Dynamic[, Initialization :> FrontEndExecute[FrontEndToken["ToggleDynamicUpdating"]]]

To return the dynamic updating back, you should use ToggleDynamicUpdating again, as you correctly mentioned in the comments:

FrontEndExecute[FrontEndToken["ToggleDynamicUpdating"]]
a = {1, 2};
Dynamic[a[[2]]]

Alternatively, you could program not to save output cells when you close your notebook according to this procedure. No output - no issues with dynamic update =)

$\endgroup$
3
  • $\begingroup$ Works, but I would prefer not to lose the output, if possible. Thanks. $\endgroup$
    – bbgodfrey
    Feb 1, 2016 at 19:50
  • $\begingroup$ @bbgodfrey I hope the final version of my answer is closer to what you were looking for, isn't it? $\endgroup$ Feb 1, 2016 at 20:12
  • $\begingroup$ Indeed, it is (+1). I agree with your assessment, however, that the answer by Simon Woods best meets my desired outcome. $\endgroup$
    – bbgodfrey
    Feb 1, 2016 at 21:03
3
$\begingroup$

Just returning to this question now and after reading your addendum I don't think you have adequately set up your test. For example here we see that when the kernel stops the value of a is not preserved and you get error boxes appearing:

enter image description here

If you want a to be Global then try this:

Dynamic@If[ListQ[a] &&Length[a]>1&& TrueQ[a[[1]] > 0], Dynamic[a[[2]]], Spacer[0]]

enter image description here

It is best to localise your dynamic variables rather than have them global. In order to localise the variable and have its value stored within the notebook you need to make it a DynamicModule variable ...which you haven't done in any of your examples. If it is a DM variable then it will "survive" the kernel session.

enter image description here

$\endgroup$
1
  • $\begingroup$ I agree that DynamicModule is to be preferred, and I use it in my actual code. It is not practical, however, to put the equivalent of the a definition in it, because doing so would encompass the entire code. $\endgroup$
    – bbgodfrey
    Feb 2, 2016 at 2:01

Your Answer

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

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