Re: Re: scope all wrong? in Mathematica 4.1
- To: mathgroup at smc.vnet.net
- Subject: [mg31914] Re: Re: scope all wrong? in Mathematica 4.1
- From: "Alan Mason" <swt at austin.rr.com>
- Date: Wed, 12 Dec 2001 04:13:53 -0500 (EST)
- References: <9v2607$ldc$1@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
Hello. 1) I think that ideal behavior would be to issue a warning "argument of function is shadowed by local variable, will have no effect" and just use the local x. To barge right in and replace x in the body of the Module when this x should refer to the local variable strikes me as too simplistic and is therefore a surprise. Perversely, badly written code is not always a waste of time, because it can reveal interesting things about how a system operates. For example, people are always throwing crap at C compilers; there are even contests to see who can write the most obfuscated C code. I tried in my previous post to express what I think would have to be changed to accommodate "ideal" behavior. In essence, some processing (and therefore unHolding) of the RHS of := -- to determine the locals and look for name clashes, and if neccessary preempt the pattern matcher -- would have to occur before the value that the system has determined for the pattern x_ on LHS is passed in to the RHS. Currently, this passing is essentially instantaneous. I concede that the above "ideal" behavior would have no practical benefits (that I can think of) and it could burden all functions with undesirable overhead. I can also see that Mathematica, unlike C, is not really obliged to behave in ways that have been specified by outside committees. 2) My comment about the local x$9 reemerging as a de facto global (growing wings as it were and flying the coop) does seem relevant to Fateman's concern about scope violation and "escaping" variables. Variables like x$9 are normally off-limits to programmers outside of the subroutine in which they are declared as local. Does Mathematica rely on the uniqueness of x$n variable names to keep track internally of multiple versions of global rules generated programmatically inside a Module, by using them in effect as part of their "signature"? I know that I can change rules after the fact (i.e., after the scope of x$n as originally declared in its subroutine has disappeared) by changing the x$n to which they have been "hard-wired". Of course, no one who has used Mathematica entertains for a moment the possibility that local variables are escaping wholesale -- this would make Mathematica completely unusable, whereas in practice it's eminently usable (albeit with a steep learning curve). But the observed phenomenon does seem to be a kind of "back door" and therefore not exactly kosher... Alan PS. I think for clarity it would be best to include a code snippet showing exactly what I mean here. Here's a greatly abridged example from actual code: \!\(\(\(setRules[sym_: D, \ delayCircleDotEvaluation_: 0]\ := \ Module[{\ h, \ symL}, \[IndentingNewLine]If[Head[sym]\ =!= \ List, \ symL\ = \ {sym}, \ symL\ = \ sym]; \[IndentingNewLine]SetAttributes[ SmallCircle, {OneIdentity, \ Flat}]; \[IndentingNewLine]a_\ \[SmallCircle]\ b_\ /; \ Head[a] === Plus\ || \ Head[b] === Plus := \ Distribute[h[a, \ b]]\ /. h -> SmallCircle\ ; \ \[IndentingNewLine]\((a_. \ S_\_u_)\)\ \ \[SmallCircle]\ \((b_\ \ c_)\)\ := \ a\ b\ \ S\_u\ \[SmallCircle]\ c\ + \ a\ S\_u\ \[CircleDot]\ b\ c\ /; \ MemberQ[symL, \ S]\ \ && \((FreeAllQ[b, symL]\ || \ Head[b] === CircleDot)\);\[IndentingNewLine]];\)\(\[IndentingNewLine]\ \) \)\) If you run setRules and then do DownValues[\[SmallCircle], pick out the rule involving S, and do a FullForm, you will not find S but rather symL$n instead (its value is in fact that of S, but it is being held; Cases[rule, symL$n, {0, Infinity}] returns {}). If you change symL$n interactively, you will change rule accordingly. (But I thought symL$n was local! So this really is a back door.) A side observation possibly of interest: If we change the code in setRules so that S is not first copied to symL (i.e., not "mediated") but used directly in the rule, the value of S does appear when the rule is examined using DownValues. This seems to shed some light on Mathematica's timing -- the value found for S_ is passed to RHS of := very early and is not held but treated as "raw". "David Withoff" <withoff at wolfram.com> wrote in message news:9v2607$ldc$1 at smc.vnet.net... > > In general, Mathematica has complicated rules for when and how its functions > > hold their arguments, which can lead to semantic surprises. Users can > > change these attributes at their own risk. In particular, the right-hand > > side of a SetDelayed such as uu[...] := x is normally not evaluated, and the > > left-hand side is normally wrapped in HoldPattern. Just how these rules > > work in conjunction with the pattern matcher is a mystery, but > > they definitely are not working correctly in Fateman's first example --- > > rr[x_] := Module[{x}, x = 5; Print["x is ", x]]. > > The system needs to unwrap the various Holds in the right order and process > > first the > > first argument {...}of Module giving the locals and preempt the pattern > > matcher if there is a clash. Presumably this should be done before > > Mathematica's uniqueifying rules (appending $n to local variable names to > > make > > them unique) are performed. Could be a timing problem. > > I presume from all of those speculations and non-specific concerns > that you suspect there is something wrong but that you aren't quite > sure what it is. Is there some way that you could be more specific? > Do you have any examples of "complicated rules" or "semantic > surprises" that might help to explain your concerns? What exactly > is "definitely ... not working correctly" about that example? Do > you have a specific description of what you think that example > should do, and why? What are the "various Holds" that you are > referring to here? > > I can imagine two potential criticisms of Mathematica here, one > of which might be partially valid, and the other of which is not > valid at all. > > The potentially sensible criticism lies within the fact that you found > this behavior confusing. In some abstract, ideal world, all of the > things that we use, from VCR's to automobiles to computer software, > would be completely intuitive, and everything would behave as expected. > Any time someone is confused by Mathematica there is at least the > possibility that there is something about the design of Mathematica > that invites that confusion. > > In this example, however, I just don't see it. If I translate > > rr[x_] := Module[{x}, x = 5; Print["x is ", x]] > > into C, for example, I get > > int rr(int x) {int x; x = 5; printf("x is %d\n", x);} > > which generates a warning message in my C compiler and produces > system-dependent results when I run the program. Most C programmers > would (I hope) immediately see the error of using the same name both > as a function parameter and as a local variable. I suppose it could > be argued that there is also something wrong with C and with the > many other programming languages that behave this way, but other than > that, I don't see what it is about Mathematica that might lead one to > expect behavior other than what is found in other languages. If > anything, the behavior of Mathematica is more straightforward than > other languages. At least it isn't system-dependent, and even > an intermediate understanding of how Mathematica works would > allow one to anticipate what this example will do. > > The other potential criticism, which so far doesn't appear to be > valid at all, is that there is something objectively wrong with > the design of this aspect of Mathematica; that the design includes > a violation of some unspecified Sacred Principle that is well known > to people with advanced degrees in computer language design, but > that is probably beyond the understanding of everyone else; but > that everyone should nevertheless be Very Worried that these problems > are lurking around like a bogeyman in the dark, waiting to bite you > in the middle of a large program. > > The reality is that there is no bogeyman, that this aspect of > Mathematica is pretty straightforward, and that in all essential > details these design choices have extensive precedent in other > programming languages. > > This still leaves the subjective criticism. Is there something > about the design of Mathematica that suggests that it should > behave unlike other common programming languages? > > There were a few other examples here, but the analysis was all > so broad and muddled that I hope that anyone who is interested > will follow up with a more specific question. > > Dave Withoff > Wolfram Research >