3
$\begingroup$

During the execution of the following code a column of three lists and two sliders are displaying in output. The first list updates if either a or b changes. The second list updates only if the value of a is changed. Similarly, the third list updates only if the value of b is changed.

a = 0;
b = 0;
Column[
{
  Dynamic[{a, b}, TrackedSymbols :> {a,b}],
  Dynamic[{a, b}, TrackedSymbols :> {a}],
  Dynamic[{a, b}, TrackedSymbols :> {b}],
  Slider[Dynamic[a], {0, 1}],
  Slider[Dynamic[b], {0, 1}]
}
]

Next I would like to replace {a,b} by a list x with two elements:

x = {0, 0};
Column[
{
  Dynamic[{x[[1]], x[[2]]}, TrackedSymbols :> {x}],
  Dynamic[{x[[1]], x[[2]]}, TrackedSymbols :> {x[[1]]}],
  Dynamic[{x[[1]], x[[2]]}, TrackedSymbols :> {x[[2]]}],
  Slider[Dynamic[x[[1]]], {0, 1}],
  Slider[Dynamic[x[[2]]], {0, 1}]
}
]

It is easy to check that now only the first list updates. Please help me to solve this problem.

$\endgroup$
4
  • 4
    $\begingroup$ My first thought is that x[[1]] is not a Symbol. The dynamic updating system probably only tracks symbols, not parts of them, so probably you can't do it the second way. $\endgroup$
    – Michael E2
    Sep 17, 2013 at 15:09
  • $\begingroup$ I believe TrackedSymbols must be taken strictly; i.e., it accepts only symbols, not expressions. $\endgroup$
    – m_goldberg
    Sep 17, 2013 at 16:00
  • $\begingroup$ I presume you are aware that you can write {a, b} = {0, 0} in your first example, so I ask: why doesn't that work for you? $\endgroup$
    – m_goldberg
    Sep 17, 2013 at 16:10
  • $\begingroup$ @m_goldberg, thank you for your comment. I want to write a code, which manipulates a big list (say 20 elements). I want to display the list and update it only when its first element is changes. Moreover, I don't want to use additional "tester" variables like Dynamic[x[[1]], (x[[1]] = tester = #1) &] ... TrackedSymbols :> {tester} $\endgroup$ Sep 17, 2013 at 16:53

2 Answers 2

3
$\begingroup$

You can create your own list of symbols with Unique.

Clear[x];
nVars = 20;
x = Table[Unique[x], {nVars}];
vars = Map[Hold, OwnValues@x, {-1}][[-1, -1]]
(# = 0.) & /@ x; 

(* {Hold[x$363], Hold[x$364], ...} *)

It's convenient to store the held variables, since once they are initialized, it's tricky to get the symbols unevaluated. We can get at the symbols via various tricks:

vars[[2]] /. Hold[var_] :> (TrackedSymbols :> {var}
(* --> TrackedSymbols :> {x$364} *)

Dynamic @@ vars[[3]]]
(* --> Dynamic[x$364] *)

Here's an example like the one in the question.

Grid[Transpose@
  {Table[Dynamic[x, #] &[vars[[i]] /. Hold[var_] :> (TrackedSymbols :> {var})],
     {i, Length@x}],
    Table[Slider[Dynamic @@ vars[[i]]], {i, Length@x}]}
]

Here's the output for nVars = 4, where each slider has been clicked once in turn:

Screenshot of output

$\endgroup$
11
  • $\begingroup$ Thank you for your smart trick. I would like to ask you, what is the role of the Refresh function ? Namely, why you don't use shorter possibility like this Table[Slider[Dynamic @@ vars[[i]]], {i, Length@x}] Table[Dynamic[x, Evaluate[vars[[i]] /. Hold[var_]:> (TrackedSymbols :> {var})]], {i, Length@x}] $\endgroup$ Sep 17, 2013 at 22:28
  • $\begingroup$ Actually what confuses me is why I seem to have to inject TrackedVariables in there twice. Doing it once does not always work. In any case, your example does not work for me from a fresh kernel in V9.0.1. For the first Dynamic[x,...], I get symbols x$363 etc. that are never updated. Of all the variations I tried, only the one with Refresh worked in all cases. I'm afraid I have not completely figured out why yet. $\endgroup$
    – Michael E2
    Sep 17, 2013 at 22:55
  • $\begingroup$ It is amasing, but I got such problem with your version. By the way, if I evaluate the code twice, the symbols are starting to uptate. I use also V9.0.1. In my example the sliders are constructed first. Maybe they initialize the sybols and the updating becomes possible ? $\endgroup$ Sep 17, 2013 at 23:11
  • $\begingroup$ @VahagnPoghosyan Oops, I forgot to copy the initialization line -- your comment made me notice. Now it should work. I'm not sure why the symbols need initialization. For instance {Dynamic@y, Slider[Dynamic@y]} does not need to have y initialized beforehand. $\endgroup$
    – Michael E2
    Sep 18, 2013 at 1:11
  • $\begingroup$ I must be missing something; why don't you merely define vars = Hold /@ x ? $\endgroup$
    – Mr.Wizard
    Sep 18, 2013 at 2:28
2
$\begingroup$

Using the ideas/tricks/solutions given in comments, I arrived to the following compact code, which uses only the variables x, x1, x2, ...

nVars = 10;
Clear @@ Names["x" ~~ DigitCharacter ...]
x = Table[ToExpression["x" <> ToString[i], InputForm], {i, 1, nVars}]

Column[Table[
ToExpression["x" <> ToString[i], InputForm, Hold] /. Hold[var_] :>
    Dynamic[Evaluate[x], TrackedSymbols :> {var}]
, {i, 1, nVars}]]

Column[Table[
ToExpression["x" <> ToString[i], InputForm, Hold] /. Hold[var_] :> Slider[Dynamic[var]]
, {i, 1, nVars}]]
$\endgroup$
2
  • $\begingroup$ Feel free to unaccept mine and accept your own. I think it is better, and future visitors would appreciate having the best answer marked. Unless someone else posts an even better solution. $\endgroup$
    – Michael E2
    Sep 18, 2013 at 13:08
  • $\begingroup$ @MichaelE2, this answer is based on the ideas of your answer and comments. Both answers are acceptable for me. $\endgroup$ Sep 18, 2013 at 13:15

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.