# How do you properly create Buttons to change dynamic variables using Table

In this example, I want a series of four buttons to change the value of a variable that is used dynamically to drive a plot. I am trying to figure out why using Table around the buttons causes a problem.

This works:

{Button["1", freq = 1], Button["2", freq = 2], Button["3", freq = 3],
Button["4", freq = 4]}
Dynamic[Plot[Sin[freq * x], {x, 0, 2 \[Pi]}]]


Why doesn't this work:

Table[Button[ToString[i], freq2 = i], {i, 4}]
Dynamic[Plot[Sin[freq2 * x], {x, 0, 2 \[Pi]}]]

-
Strongly related: mathematica.stackexchange.com/q/7756/121 – Mr.Wizard Jul 14 '12 at 4:44

The second one does not work, because Button has HoldRest property:

In[1]:= Attributes[Button]


Thus, i in your buttons are interpreted as literal i, not numbers.

The easiest way to solve this is using a Map:

Map[(Button[ToString[#], freq2 = #]) &, Range[4]]
Dynamic[Plot[Sin[freq2*x], {x, 0, 2 \[Pi]}]]


When each value is applied to the pure function, # will be replaced with the actual value.

# PS

Just for fun, you can confirm these by using Shift-Ctrl-E (or Shift-Cmd-E on Mac) on your button cell (exposing underlying FE language). This is what you see when expanding the button cell from the original code:

As you can see, the action assigns i to freq (all in $CellContext), not actual value (1, this case). - Thank you, that makes perfect sense. – ebergerson Jul 17 '12 at 19:10 Look at the FullForm of the two lists: {Button["1", freq = 1], Button["2", freq = 2], Button["3", freq = 3], Button["4", freq = 4]} //FullForm (* List[Button["1",Set[freq,1]],Button["2",Set[freq,2]],Button["3",Set[freq,3]],Button["4",Set[freq,4]]] *) Table[Button[ToString[i], freq2 = i], {i, 4}] // FullForm (* List[Button["1",Set[freq2,i]],Button["2",Set[freq2,i]],Button["3",Set[freq2,i]],Button["4",Set[freq2,i]]] *)  In the second case you Set your freq2 equal to the symbolic i, not to the value of the iteration variable. That's because Button has the attribute HoldRest. A possible way out would be to inject the value in the variable using With, i.e. Table[With[{j = i}, Button[ToString[i], freq2 = j]], {i, 4}] //FullForm (* List[Button["1",Set[freq2,1]],Button["2",Set[freq2,2]],Button["3",Set[freq2,3]],Button["4",Set[freq2,4]]] *)  Moreover, this is referenced in the documentation for Button, at Scope$\rightarrow\$ Button Control.

-
Yes, I see here, as above, the i was not being evaluated. Thank you for your help. – ebergerson Jul 17 '12 at 19:10

As already stated this is an evaluation problem because of the Hold attribute that Button has, and the mechanism of Table which is akin to Block. You need a way to get the value into the expression. In this case I would use Function and Array:

Array[Button[#, freq2 = #] &, 4]

Dynamic @ Plot[Sin[freq2*x], {x, 0, 2 π}]


(ToString is unnecessary.)

See the answers to this question for other options:

Using pure functions in Table

-
+1 for the minimalistic cool code – R Hall Jul 14 '12 at 15:54
Thank you. Nice to see the alternative Array to Map above. I would not have thought of the alternative. – ebergerson Jul 17 '12 at 19:12