1
$\begingroup$

I want to create a list of values, True or False, and to update those values with a Checkbox. But the number of elements needs to be arbitrary.

It should look something like the following code which works perfectly fine:

dyn={False,False,False};
A={{1,dyn[[1]]},{2,dyn[[2]]},{3,dyn[[3]]}}
Row@{Checkbox@Dynamic@dyn[[1]],Checkbox@Dynamic@dyn[[2]],Checkbox@Dynamic@dyn[[3]]}

But, of course, it is not practical to write out every iteration of these things. This is the reason that Table exists. However, when I put everything into tables, it does not work.

n=3;
dyn=Table[False,{i,n}];
A=Dynamic@Table[{i,dyn[[i]]},{i,n}]
Row@Table[Checkbox@Dynamic@dyn[[i]],{i,n}]

The code above results in this error message:

Part::pspec: Part specification i is neither an integer nor a list of integers. >>

I do not understand why Table and Dynamic are in conflict with one another. It is as if Dynamic reaches the i before Table and replace it with an iterative value and then Dynamic has no idea what to do with it. But why is this? Or is the problem something else altogether?

$\endgroup$
1
  • $\begingroup$ Sounds like a job for Module or With; using these will allow you to limit the context of your counting variable. $\endgroup$
    – IPoiler
    Commented Jul 29, 2015 at 15:19

2 Answers 2

2
$\begingroup$

Compare the output of this:

Table[ Dynamic[i], {i,3}]  (* gives {i,i,i} *)

with this:

Table[ With[{i=i},Dynamic[i]], {i,3}]  (* gives {1,2,3} *)

Now you can use that:

a = Range[3];
Table[ With[{i=i}, Dynamic[ a[[i]] ] ], {i,3}]  (* gives {1,2,3} *)

Then:

a+=1;   (* changes output above to {2,3,4} *)

Addendum to address question in the comments below: You can look at the Attributes of a function (in this case Dynamic). If you see that it has a HoldFirst (or HoldRest, or HoldAll) attribute, then that tells you some of its arguments will not be evaluated. For example, consider:

Attributes[foo] = {HoldFirst};
Table[ foo[i], {i,3} ]   (* gives {foo[i], foo[i], foo[i] *)
Table[ With[{i=i},foo[i]], {i,3}]  (* gives {foo[1], foo[2], foo[3] *)
$\endgroup$
2
  • $\begingroup$ Thank you so much. That answers the question. Out of curiosity, precisely what was the problem? How can I avoid this in the future? Thanks again! $\endgroup$
    – cbward90
    Commented Jul 29, 2015 at 15:51
  • $\begingroup$ I added some info in the answer. Also this post is useful; if you read it you will likely avoid many common programming conundrums: mathematica.stackexchange.com/questions/18393/… $\endgroup$ Commented Jul 29, 2015 at 16:26
2
$\begingroup$

One possibility is to use MapIndexed:

n = 3; dyn = Table[False, {i, n}];
A = Dynamic@Transpose[{Range[n], dyn}]
MapIndexed[Checkbox[Dynamic[dyn[[#2[[1]]]]]] &, Range[n]]
$\endgroup$
2
  • $\begingroup$ similarly Table[ Checkbox[Dynamic[dyn[[#]]]] &@i , {i, 3}] $\endgroup$
    – george2079
    Commented Jul 29, 2015 at 19:21
  • $\begingroup$ @george2079 Yes. Or, of course, just Map[Checkbox[Dynamic[dyn[[#]]]] &, Range[n]] $\endgroup$ Commented Jul 29, 2015 at 20:51

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.