4
$\begingroup$

I was trying to create a Manipulate with a variable number of controls for the elements of an array. Normally, you can inject the value of an iterator i with With[{i = i},...] into Dynamic[..]. This works, but surprisingly, it does not inject the value into the instance of i outside the Dynamic[].

With[{$maxterms = 4}, Manipulate[ a[[;; terms]], {{a, ConstantArray[0., $maxterms]}, None}, {{terms, 2}, Range@$maxterms}, Dynamic@ Column@ Table[ With[{i = i}, Control[{ {a, ConstantArray[0., $maxterms], Subscript["a", i]}, (* i not injected *) 0., 1, Manipulator[Dynamic[a[[i]]], ##2] &}] (* i is injected *) ], {i, terms}] ] ] 

Using a fixed number of controls works:

With[{$maxterms = 4}, Manipulate[ < same three lines >, Evaluate@ Column@ Table[ < same With[] code >, {i, $maxterms}] ]] ] 

Apparently, the difference is Dynamic@... vs. Evaluate@.... The second code does not work if Evaluate is omitted.

Question: As a workaround, one can dynamically select from the Table[] in the second method, but why does the Dynamic construction in the first case fail?

$\endgroup$
2
  • 1
    $\begingroup$ For the first scenario, writing instead Dynamic@Subscript["a", i] makes the injection. Could it be that without this Dynamic, Manipulate does not bother to inject? This seems to be the case when removing Dynamic from Manipulator and writing instead Manipulator[a[[i]], ##2] &. $\endgroup$ Commented Oct 22, 2016 at 15:39
  • $\begingroup$ @xavier Yes, that's a nicer workaround. I'm not sure what Manipulate[] is doing yet. It must be rewriting the code in some way. I guess I'm wondering whether it's a bug or I'm breaking some rule. $\endgroup$ Commented Oct 22, 2016 at 17:28

1 Answer 1

4
$\begingroup$

This is just a partial answer.

Manipulate[] is rewriting the code in a way that breaks With[]. If we look that the InputForm of the evaluated code, we see that the code for Control[..] has been tagged with the option ControlPlacement -> 1, which apparently marks it to replace the placeholder Manipulate`Place[1].

With[{$maxterms = 4}, Manipulate[ a[[;; terms]], {{a, ConstantArray[0., $maxterms]}, None}, {{terms, 2}, Range@$maxterms}, Dynamic@ Column@ Table[ With[{i = i}, Control[{ {a, ConstantArray[0., $maxterms], Subscript["a", i]}, (* i not injected *) 0., 1, Manipulator[Dynamic[a[[i]]], ##2] &}] (* i is injected *) ], {i, terms}] ] ] // InputForm 

Input form:

Manipulate[ a[[1 ;; terms]], {{a, {0., 0., 0., 0.}}, 0, ControlType -> None}, {{terms, 2}, {1, 2, 3, 4}}, {{a, {0., 0., 0., 0.}, Subscript["a", i$]}, 0., 1, Dynamic[Manipulator[Dynamic[a[[i$]]], ##2] & ], ControlPlacement -> 1}, Dynamic[Column[ Table[With[{i$ = i}, Manipulate`Place[1]], {i, terms}]]] ] 

What is still unclear is how With[{i$ = i}, Manipulate`Place[1]] results in the symbol i$ being replaced by the value of i. It seems to have something to do with being wrapped in Dynamic[].

For instance, if we add a Dynamic@ to Subscript["a", i] in the following two ways, only the first of the two works:

Dynamic@Subscript["a", i] (* WORKS (@xavier's workaround) *) Subscript["a", Dynamic@i] (* does NOT work *) 

However, both codes work if we use a replacement rule instead of With to inject the value of i; just replace the original Control[..] code inside Table[] with this:

Control[{{a, ConstantArray[0., $maxterms], Subscript["a", Dynamic@i] (* or replace with Dynamic@Subscript["a", i] *) }, 0., 1, Manipulator[Dynamic[a[[i]]], ##2] &}] /. HoldPattern[i] -> i 

But the replacement rule method fails just like With in the OP if the control label is just Subscript["a", i], not being wrapped by Dynamic[].


Going back to the input form of the original code, I would expect Manipulate`Place[1] might be replaced by the control. Something like this:

DynamicModule[{terms = 2, a = {0., 0., 0., 0.}}, Dynamic[Column[Table[With[{i$ = i}, Manipulate`Place[1]], {i, terms}]]] /. Manipulate`Place[1] -> Control@{{a, {0., 0., 0., 0.}, Subscript["a", i$]}, 0., 1, Dynamic[Manipulator[Dynamic[a[[i$]]], ##2] &], ControlPlacement -> 1} ] 

Mathematica graphics

But as can be seen, that actually works, so something else must be happening.

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.