18

I'm putting my new copy of Mathematica 10 through its paces and I noticed a weird change in the colouring scheme that I find very annoying, and I'd like to get some insight into why it's happening.

The change happens, as far as I can tell, for variables that have been set in some scoping construct which are then used inside of a Manipulate command. Thus, for example, the code

Module[
 {A = 1},
 Manipulate[
  Plot[
   A Sin[k x]
   , {x, 0, 20}
   ]
  , {k, 1, 10}
  ]
 ]

renders differently in the Mathematica 9 and 10 frontends:

enter image description here

Playing around in Edit > Preferences > Appearance > Syntax Coloring > Errors and Warnings, the error class that this is attributed to is

Variables that will go out of scope before being used

though what that means exactly isn't very clear to me. Therefore, I have some questions:

  • Is this in fact an incorrect usage? If so, why, and what alternative construct should I use? (I notice, in particular, that in version 10 the red colour is displayed for Block and Module but not for With.)

  • Why did this only start happening in version 10? Which version is right?

  • If this sort of code is OK, can I safely disable this sort of error marking? What risks does that entail?

Emilio Pisanty
  • 10,255
  • 1
  • 36
  • 69
  • You can nest Module within Manipulate (and I think nesting it the other way around is what caused the syntax warning because the Manipulate did not play nice with the Module outside of it). Or as you said you can use With, and in this case it's acceptable to do so as A is basically just a constant that does not change its value when the code is run. – seismatica Jul 17 '14 at 12:04
  • Is there some specific reason why the inverted order (i.e. Module inside the Manipulate) is preferable? – Emilio Pisanty Jul 17 '14 at 12:05
  • I have no clue, but I'd like to add that if you nest Module within Manipulate, your Module variables can depend on the manipulate parameter, whereas you cannot achieve this the other way around (as the manipulate parameter disappears outside of the scope of the Manipulate block). You can try this to see what I'm talking about: 'Manipulate[Module[{A = k}, Plot[A Sin[3 k x], {x, 0, 20}]], {k, 1, 10}]. Of course in your case that's not going to be important since your Module variable does not change, hence the use ofWith` will be just fine. – seismatica Jul 17 '14 at 12:17
  • This is an issue for me as certain applications I'm using do need this. Note, however, that code of the form Module[{A}, Manipulate[A = k; Plot[A Sin[k x], {x, 0, 20}], {k, 1, 10}]] works fine in both v9 and v10, but only v10 colours it as incorrect syntax. – Emilio Pisanty Jul 17 '14 at 12:29
  • I think the point is that A (or rather the temporary variable A$xxx generated by Module, where xxx is some number) will be kept alive by the Manipulate even after returning from the Module. Now the variable won't go away as long as it is referenced, which I actually consider an useful feature (it allows you to implement closures). At least that's how it is in Version 8; one would hope that it didn't change in v10. Does v10 also mark the v in the following code red? Module[{v=0},next[]:=v++] – celtschk Jul 17 '14 at 13:07
  • @celtschk It doesn't. I only partially understand what you're saying. What would the code I posted, or similar code, be able to do that it wouldn't be able with a With instead of a Module. – Emilio Pisanty Jul 17 '14 at 13:54
  • Maybe I misunderstood the error class description (on second reading I'm no longer sure). Does the following give a red v? Module[{v=1},Hold[v]]? What about Module[{v=1},v]? And Module[{v=1},v;0]? And Module[{v=1},Hold[v];0]? – celtschk Jul 17 '14 at 16:43
  • @celtschk none of those have red vs. The problem, as you suggested originally, is with expressions of the form Module[{v}, Dynamic[v]] where the Dynamic output would break the localization of the variable. – Emilio Pisanty Jul 18 '14 at 10:35
  • But then I don't understand why it wasn't made red in my original example: Try adding a Print statement like this to reveal the module's local variable name: Module[{v=0},Print[Hold[v]];next[]:=v++] and then evaluate the variable outside the module; you'll see it has still the value assigned in the module. The same is true for Module[{v=1},Hold[v]] (here you get the variable name right in the result, so no Print is necessary to reveal it). Also note that while the behaviour with Block and Manipulate is pretty bad, I don't see an issue with the corresponding Module behaviour; … – celtschk Jul 18 '14 at 10:58
  • … indeed, exactly this "keeping alive" part is what allows you to implement closures using Module. – celtschk Jul 18 '14 at 10:59
  • You are correct. Both versions allow the $'d variable to leak its value to the outside, but they are not coloured red. I'm unsure, then, of how (un)desirable this feature actually is. What exactly do you mean by "implement closures"? – Emilio Pisanty Jul 18 '14 at 11:04
  • 1
    See the section "Module"/"Advanced usage" in this answer for an example of a closure. Anyway, after reading the documentation of DynamicModule I think I now figured out what the problem with Module+Manipulate probably is: Dynamic content (like Manipulate) is stored across sessions. However a normal Module variable is not stored that way. I guess that would create problems as soon as you save the notebook and later open it in a new instance of Mathematica. – celtschk Jul 18 '14 at 11:10

2 Answers2

21

Based on Mr.Wizard's answer and comments by Szabolcs and celtschk, I now understand that the code I posted does have undesirable side-effects and it should be avoided. Specifically, the scoping constructs Module and Block are meant to completely localize the variables in their first argument (for more information see this question). However, placing their scoped variables inside a Manipulate (or other dynamic construct) can cause the values to leak, and this should be avoided - hence the syntax error marks.

TL;DR:

Behaviour of the form

Block[{v}, Dynamic[v = 1]]
v

(*
1
1
*)

is unwanted. Scoping constructs which contain Dynamic objects like Manipulate should be replaced by With or DynamicModule.

Modules localize their variables by creating new local variables that are unique for the session. Thus, inside Module[{A}, ... ], the variable A gets replaced by a variable of the form A$1234, and this should not be accessible outside of the Module:

Module[{A},
 Print[A]; A = 1
 ]
(*
A$464
1
*)

A$464
(*
A$464
*)

Placing a Manipulate inside the Module, though, can cause this value to leak:

Module[{A},
 Print[A];
 Manipulate[A = k, {k, 1, 2}]
 ]

will produce e.g. A$524 and the Manipulate, and then asking for that variable gives

A$524
(*
1
*)

Block is similar but slightly worse, as it is now the value of the scoped variable itself that can leak. The expected behaviour is

Block[
 {A},
 Print[A];
 A = 1
 ]
A
(*
A
1
A
*)

but with a Manipulate inside, the value of A outside the Block can change:

Block[{A},
 Print[A];
 Manipulate[A = k, {k, 1, 2}]
 ]

returns A and the Manipulate, and then asking for A returns

A
(*
1
*)

This is indeed incorrect and should be avoided.

The correct way to go about it, then, appears to be using a DynamicModule whenever there are dynamic objects inside the scoping construct. This type of Module is indeed capable of containing the side effects described above. Thus,

DynamicModule[{A},
 Print[A];
 Manipulate[A = k, {k, 1, 2}]
 ]

will produce e.g. A$827 and the Manipulate, and now the scoped variable A$827 is properly contained:

A$827
(*
A$827
*)

For further details about this, and about the differences between Module and DynamicModule, see Advanced Dynamic Functionality - Module versus DynamicModule. For more on the behaviour of Module, Block and With in different circumstances, see this question.

Emilio Pisanty
  • 10,255
  • 1
  • 36
  • 69
8

I believe that highlighting is there specifically to encourage you to use DynamicModule rather than Module:

DynamicModule[{A = 1}, Manipulate[Plot[A Sin[k x], {x, 0, 20}], {k, 1, 10}]]

One reference:

Also related:

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • So the rule of thumb is to use DynamicModules whenever there are Dynamic-like constructs like Manipulate inside? – Emilio Pisanty Jul 17 '14 at 14:14
  • 2
    Manipulate is evaluated in a special way, that I don't understand fully. It is not actually evaluated, just formatted in a special way. After creating a Manipulate, checking its InputForm shows that the head is still Manipulate. Anyway, the point is that by the time the guts of Manipulate get evaluated, that variable A is not localized any more. ... – Szabolcs Jul 17 '14 at 14:14
  • 4
    ... For some reason, the Manipulate still seems to work as one would naively expect, but that's only because A$1234 has leaked from Module and is not being cleared as it normally would. To sum up: it looks like a very bad idea to use Module around Manipulate. – Szabolcs Jul 17 '14 at 14:15