Re: Combining Slider and SetterBar in Manipulate
- To: mathgroup at smc.vnet.net
- Subject: [mg115255] Re: Combining Slider and SetterBar in Manipulate
- From: John Fultz <jfultz at wolfram.com>
- Date: Wed, 5 Jan 2011 05:47:35 -0500 (EST)
On Tue, 4 Jan 2011 18:53:35 -0500 (EST), AES wrote: > In article <ifup6c$cnr$1 at smc.vnet.net>, > JohnH <ununquadium113 at yahoo.com> wrote: > >>> Also...a bit of unsolicited advice. Your use of Block is a *bad* idea. >>> It's always bad to reference Block-scoped or Module-scoped variables >>> declared outside of a Manipulate or Dynamic from within that >>> Manipulate/Dynamic. If you're wanting to localize the variable >>> 'someData', then Manipulate offers you an easy way to do that. Add >>> someData as a control variable, but no control appearance. >>> > John, I haven't followed the earlier part of this thread (and scoping is > something I try to think about as little as possible!), but could you > expand on this a little? > > As an old Fortran programmer, I think in terms of subroutines. So, in > building a Manipulate I want to first define a "subroutine" (that is, a > Module) which depends on, say, 2 or 3 explicit arguments, plus maybe a > few global parameters which will have already defined values. This > subroutine will then return a numerical value or maybe a graphics object. > > Then I want to build a Manipulate in which some or all of the explicit > arguments are controlled by Controls (others may be explicitly set > within the Manipulate); call this subroutine (or maybe several such > subroutines) within the Manipulate; and Plot or Show the object > returned by the subroutine, or something that depends closely on it, > still within the Manipulate. > > I guess the primary objective of this approach is brevity of code within > the Manipulate, plus just general modularity. Is the above a bad > approach? -- especially assuming that the overall notebook containing > the Manipulate will be relatively brief and self-contained, and one > needn't worry about side effects after the Manipulate has been used. Sorry, there's no way to avoid discussing some detail of scoping to answer your question, but I'll try to make it as painless as possible. As you probably know, Manipulate is built on top of Dynamic. I know you're probably much more interested in Manipulate, but it's easier to explain if I reference Dynamic directly. But, in most places in my explanation, you can replace "Dynamic" with "Manipulate" and get the basic idea. The important thing to understand about Dynamic is that when you evaluate a Dynamic, it does *not* immediately evaluate its contents. This is why, for example, that... Dynamic[x==5];0 ...does not, in fact, assign x the value 5. A Dynamic, and therefore a Manipulate, only gets evaluated when it gets displayed onscreen. This is a real problem when you surround Dynamic or Manipulate with Block or Module. These scoping constructs have long since evaporated away by the time the Dynamic gets evaluated, and so any scoping they did for the contents of Dynamic is pretty much useless. E.g., In[1]:== Block[{x==5},Dynamic[x]] Out[1]== x Incidentally, in this case, a bit of syntax coloring warns you that something bad may happen. Module is worse because it's a kind of scoping construct where the scoping implementation can leak out. So, you might know that, for example: In[2]:== Module[{x},x] Out[2]== x$139074 But what's trickier is what happens with Dynamic. Because at first it looks like it works: In[3]:== Module[{x==5},Dynamic[x]] Out[3]== 5 but this is just another form of Module leakage. In[4]:== %//InputForm Out[4]//InputForm== Dynamic[x$139080] Recall that Dynamic did not evaluate its argument right away, so in fact, it just carried the substituted 'x' straight out of the Module. There are two scoping constructs which work well with Dynamic -- DynamicModule and With. DynamicModule[] works because, like Dynamic, it lives inside the front end. So, it localizes variables exactly when the Dynamic evaluates. With[] works because it's essentially a form of find-and-replace for expression trees, rather than an attempt to localize variables. Also, substitution of named function variables works well. Function variable substitution is a lot like With[]. This should slot very naturally into your Fortran experience. And you can generally use DynamicModule[] wherever you would have used Module[] before. But Block[]...well, that's just not a concept which is compatible with how Dynamic works. Understand that this only affects scoping constructs used outside of Dynamic (or Manipulate). Using them inside is just fine. Sincerely, John Fultz jfultz at wolfram.com User Interface Group Wolfram Research, Inc.