7
$\begingroup$

I'm confused about the best approach to localizing symbols used in a Manipulate. I understand that Manipulate does a good job by default of localizing symbols defined in its list of controls (even if these are custom controls). But it appears that symbols defined in the first argument, or those initialized with an Initialization option, are not localized. For example, in the following, z, r, and q (and naturally x) are local, but y and t are not:

Manipulate[
    y = 4*x;
    Plot[y*x^z+t[q], {x, 0, r}],
    {z, 0, 5},
    Row[{Control@{{r,2}, 2, Dynamic@q}}],
    {{q,10}, 5, 20},
    Initialization:> (t[i_]:=5*i)
]

Wrapping the whole Manipulate in a Model[{y,t}, ... seems to work, but marks y and t in the Manipulate in red (on macOS) which leaves me wondering if it's the right thing to do.

There are two approaches that seem to work partially, but not altogether:

DynamicModule

Wrapping in DynamicModule works to localize any symbols not localized by Manipulate

DynamicModule[{y,t},
    Manipulate[
        y = 4*x;
        Plot[y*x^z+t[q], {x, 0, r}],
        {z, 0,5},
        Row[{Control@{{r,2}, 2, Dynamic@q}}],
        {{q,10}, 5, 20},
        Initialization:> (t[i_]:=5*i)
]]

but this places y and t in an outer scope, which seems the wrong way to proceed.

ControlType -> None

For some symbols, the form {sym, None} works to localize sym, but only it seems for limited cases. For example

Manipulate[
    y = 4*x;
    Plot[y*x^z+t[q], {x, 0, r}],
    {z, 0, 5},
    Row[{Control@{{r,2},2,Dynamic@q}}],
    {{q,10}, 5,20},
    {y, None},
    Initialization:> (t[i_]:=5*i)
]

localizes y. But similar attempts to localize a function such as t fail.


What is the correct approach to localizing symbols inside Manipulate? Is there are reason to prefer DynamicModule over ControlType -> None in general, or vice versa? How should local functions be localized (esp. if the natural thing to be ding is specifying them in Initialization)?



Additionally, controls defined with Control@ don't highlight the associated symbols to indicate localization, which makes it very hard to read through code and understand how things are scoped. DynamicModule can be used to fix this (and even leaves the symbol in the inner Manipulate scope).

$\endgroup$
5
  • 1
    $\begingroup$ Manipulate only localizes control variables. If you want more localization see DynamicModule. Since Manipulate is a front-end thing (it's a cousin of Dynamic) you'll want the front-end version of Module--i.e. DynamicModule. In fact Manipluate resolves to a DynamicModule when viewed. $\endgroup$
    – b3m2a1
    Sep 5, 2017 at 15:42
  • $\begingroup$ To localize, for example r, you can add {{r, 2}, None} after {{q, 10}, 5, t}. $\endgroup$
    – Karsten 7.
    Sep 5, 2017 at 15:45
  • $\begingroup$ Let us continue this discussion in chat. $\endgroup$
    – b3m2a1
    Sep 5, 2017 at 16:11
  • 1
    $\begingroup$ Closely related: 17112, 72422 $\endgroup$
    – Kuba
    Sep 5, 2017 at 16:41
  • 1
    $\begingroup$ Also related: 13658, It is possible that much of what is discussed in the comments has been fixed in the intervening (nearly) five years. $\endgroup$
    – m_goldberg
    Sep 5, 2017 at 17:10

2 Answers 2

5
$\begingroup$

Because of the interactions of the various sliders, I would wrap the Manipulate expression in a DynamicModule expression that defines and localizes y and t. I would also define y as a function. Like so:

DynamicModule[{y, t},
  Manipulate[
    Plot[y[x]*x^z + t[q], {x, 0, r}],
    {z, 0, 5, Appearance -> "Labeled"},
    Row[{Control @ {{r, 2}, 2, q, Appearance -> "Labeled"}}],
    {{q, 5}, 5, t[i], Appearance -> "Labeled"},
    {{i, 3}, 1, 5, 1, Appearance -> "Labeled"}],
  Initialization :> (y[x_] := 4*x; t[i_] := 5*i)]

demo

I had to introduce the i slider because, without something like it, the OP's code as given in the question is not functional.

Update

My experience is that the form {{var, intitVal}, None} works well when var is used to introduce a simple variable, such as temporary used to help break up a complicated computation. To localize more complex things, such as function definitions, I prefer to take the route I show in this answer.

$\endgroup$
4
  • $\begingroup$ Fixed the bug in the code. Also focused on the several issues raised. $\endgroup$
    – orome
    Sep 5, 2017 at 18:10
  • $\begingroup$ And r? What's the reason for the different coloring; is it meant to mean something? DynamicModule fixes it (and even keeps it in the the right scope). $\endgroup$
    – orome
    Sep 5, 2017 at 19:48
  • $\begingroup$ So this method appears superior in terms of brevity and clarity. Is there any real drawback to pulling things — here y and t — out into a new nesting scope? $\endgroup$
    – orome
    Sep 5, 2017 at 20:14
  • $\begingroup$ @raxacoricofallapatorius. Not that I know of. $\endgroup$
    – m_goldberg
    Sep 6, 2017 at 0:10
3
$\begingroup$

The {var, None} spec does work for functions if you use Clear. It just initially assigns 0 to them. So you can do this:

Manipulate[
 Plot[y[x]*x^z + t[q], {x, 0, r}], {z, 0, 5, Appearance -> "Labeled"},
  Row[{Control@{{r, 2}, 2, q, Appearance -> "Labeled"}}], {{q, 5}, 5, 
  t[i], Appearance -> "Labeled"}, {{i, 3}, 1, 5, 1, 
  Appearance -> "Labeled"},
 {y, None},
 {t, None},
 Initialization :> (
   Clear[y, t];
   y[x_] := 4*x; t[i_] := 5*i)
 ]
$\endgroup$
8
  • $\begingroup$ And r? What's the reason for the different coloring? (It seem the only way to avoid it is with DynamicModule; or initializing it a second time in a ControlType -> None control.) $\endgroup$
    – orome
    Sep 5, 2017 at 19:47
  • $\begingroup$ What's wrong with r? It's colored differently because it doesn't match SyntaxInformation[Manipulate]. $\endgroup$
    – b3m2a1
    Sep 5, 2017 at 19:48
  • $\begingroup$ That's a bit circular though. The question is: if the coloring is meant to convey something, what is it meant to convey? Locals are clearly indicated, as are undefined symbols. The coloring for r corresponds to the latter. $\endgroup$
    – orome
    Sep 5, 2017 at 19:51
  • $\begingroup$ The coloring isn't handled by the kernel at all. It's handled by the front-end. The front end does static analysis to try to figure out what is what, but the front end is sometimes wrong. The coloring should be seen as a guideline. Usually the FE is right, but sometimes it misses things. $\endgroup$
    – b3m2a1
    Sep 5, 2017 at 19:52
  • $\begingroup$ Ah, ok, that makes more sense: it's wrong. $\endgroup$
    – orome
    Sep 5, 2017 at 19:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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