21
$\begingroup$

I noticed that in Mathematica's Function Navigator With is listed as being part of the "Dynamic Interactivity Language".

Mathematica graphics

It is not the first (or even the fourth, as it seems to be in this case) function that would come to my mind when discussing dynamic interactivity.

While I'm well aware of With's main purpose (which to me is injecting evaluated expressions in other, possibly held, expressions) I can't really come up with many examples of its use in a dynamic context.

One thing may be the example given on the Button doc page:

Table[With[{i = i}, Button[i, Print[i!]]], {i, 10}]

With is necessary here because Button has attribute HoldRest and without it the action of the button would be to print the unevaluated text "i!".

Is this sufficient to make With be part of the "Dynamic Interactivity Language" or are there better examples of its use that justify its listing in the Function Navigator? Examples which really need With and can't be done without?

$\endgroup$
2
  • $\begingroup$ @NasserM.Abbasi I'm not sure that really qualifies. Isn't that just With being used as a macro boilerplate generator? Its use there is to shorten things, not making things possible which weren't before. $\endgroup$ Commented Dec 23, 2012 at 23:24
  • 2
    $\begingroup$ From Doc center: "With — insert static content into a dynamic object" $\endgroup$
    – Michael E2
    Commented Dec 24, 2012 at 1:37

1 Answer 1

17
$\begingroup$

As a point of curiosity, I did a quick search in the source code used by Wolfram for various palettes, dialog boxes, and toolbars. About one in eight Dynamic constructs were accompanied by a With.

The example you provide is certainly a good one. It illustrates the general principle nicely, but what it doesn't do is to illustrate how widely the general principle applies. To review and restate your example in terms of Dynamic:

Slider[Dynamic[x], {1, 10, 1}]
Table[Dynamic[i x], {i, 1, 10}] (* wrong *)
Table[With[{i=i}, Dynamic[i x]], {i, 1, 10}] (* right *)

The "wrong" example produces, for x = 1, a list of {i,i,i,i,i,i,i,i,i,i} because Dynamic is HoldFirst, and therefore the value that Table assigned to i is never allowed to evaluate inside Dynamic.

So, in this case, Dynamic really only shares a property with any other HoldFirst (or HoldRest or HoldAll) function. But what may not be obvious is that Dynamic poses a bigger problem not shared by many of those functions, although it is shared by Button. Most functions are evaluated in a well-understood sequence of Shift-Enter evaluations. There may be tricky localizations on the part of Table, Block, or related functions, but access to unscoped variables will work quite well.

Less obvious than tight scoping constructs like Table is a much more abstract and bigger scoping construct that doesn't live inside the Mathematica language. That scoping construct is the kernel session. Once a kernel session ends, the variables disappear and become inaccessible. Stated that way, it seems pretty obvious. But the interesting part is that Dynamic (and Button) are capable of not only escaping tight scoping constructs, but they're even capable, by design, of escaping the Mathematica session. E.g., save their results in a notebook, quit Mathematica, restart, and open the notebook.

If you're holding state, then DynamicModule is the way to go. But, as is pointed out in the comments following your question, you often don't need variables for state...you're just using them as a form of macro expansion. It was for the convenience of authoring, and not at all necessary for the execution of the code, that some variables are used. And these variables are typically best deployed into a Dynamic construct using With.

And so the reason I see With frequently in the Mathematica source code is because it is really important that these interfaces fully encapsulate all initializations and definitions. Sometimes you may write an interface where you don't really care whether it has to be "prepped" by a series of Shift+Enter evaluations. But if you want the interface to really stand alone, you're almost certainly going to be relying on With.

$\endgroup$
4
  • $\begingroup$ Thanks John. As to session-level scoping: I wrote something about the dark side of this (SaveDefinitions considered dangerous). $\endgroup$ Commented Dec 24, 2012 at 20:08
  • $\begingroup$ Far more than one in eight functional units in my code use With--and, more often than not, it is nested and combined with other scoping constructs as well. Maybe the moral of the story is not so much that Dynamic has unusual semantics (although surely it does), as that With is greatly underused in general? $\endgroup$ Commented Dec 25, 2012 at 3:06
  • $\begingroup$ @OleksandrR. That's probably true. From the three main scoping constructs it seems that With receives the least attention, which is fully undeserved. $\endgroup$ Commented Dec 25, 2012 at 22:27
  • $\begingroup$ @OleksandrR. I should clarify a couple of things which skew the numbers a bit; in the WRI code I was scanning, some Dynamic/With combos are hidden behind function calls which appear many times, but because I was scanning the generator code, they only show up once in the function definition. Also, WRI code uses Dynamic frequently as a means of abstracting localization strings, which doesn't look much like end-user usage. Nonetheless, I think we agree on the basic point that where you find Dynamic, you're much more likely to find With. $\endgroup$
    – John Fultz
    Commented Dec 27, 2012 at 7:14

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.