Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Mathematica scoping / contexts / variable localization

88 views
Skip to first unread message

Leo Alekseyev

unread,
Nov 18, 2009, 7:15:10 AM11/18/09
to
Dear Mathematica gurus,

One of the things that initially made Mathematica difficult for me to
use was scoping -- in particular, the fact that all symbols by default
appear in the global namespace. Even though this is a default
behavior for interactive evaluation in many packages, e.g.
R, in Mathematica, it leads to a greater potential for errors because
unlike those languages, in Mathematica
(1). a symbol can have multiple DownValues, and
(2). if one forgets to explicitly localize a symbol inside a scoping
construct, it may silently be taken from the global namespace.

After many years I finally figured out a (more or less) clean way to
structure my code and workflow, through a combination of defining
modules, contexts, packages, and careful use of Clear and Remove.

I still wonder, however, why there isn't a construct similar to Module
that would define a unique private context for _all_ symbols within
the construct (i.e. without having to declare them in a list). You
can kind of simulate this behavior by using BeginContext["MyCont`"]
together with redefining $ContextPath temporarily to only have
"MyCont`" and "System`". This is obviously too verbose to be of
practical use, but I do wonder why there isn't a built-in construct.

I suppose my question is -- is there a deep wisdom behind its absence,
or perhaps I am an anomaly in thinking that such behavior (automatic
lexical scoping for symbols in subroutines, present in R and
many others) would be incredibly handy?..

Thanks,
--Leo

Leonid Shifrin

unread,
Nov 19, 2009, 5:25:32 AM11/19/09
to
Hi Leo,

I certainly don't qualify as a guru (and don't want to), but here are my two
cents.

1. I usually think of a notebook as an interactive development and
visualization tool (apart from it being an interactive document, the aspect
which is more relevant for presentation rather than for development),
something like a top-level in some other functional languages. Modules and
other smaller-scale localization tools should be sufficient within a
notebook, and if they are not, it's a clear sign to me that the (part of
the) functionality must be moved into a properly formed package (at least
using BeginPackage - EndPackage etc).

2. Nobody forbids you to use BeginPackage - EndPackage with inner Begin-End
and private sub-contexts within a notebook, with the same benefits as they
give you in stand-alone package files.

3. A somewhat related question about automation of the steps needed to
localize some code in a certain context was recently asked on the group. I
posted some possible solution in this thread:

http://forums.wolfram.com/mathgroup/archive/2009/Aug/msg00701.html

It is not without bugs though - I mentioned some of the limitations (all of
which can be fixed) in my post. Eventually I will fix them and have a more
complete solution available. See if the solution from my post can serve your
needs.

Regards,
Leonid

David Park

unread,
Nov 19, 2009, 5:26:16 AM11/19/09
to
I'm not certain why many people seem to have problems with localization of
symbols. I write lots of Mathematica definitions and code, I never use
CleanSlate or Remove or Clear all Global` symbols and I never get into
trouble (well, hardly ever).

There are a few simple Mathematica style principles that can avoid most such
problems.
1) Never assign values to simple symbols that you might conceivably want to
use as symbolic variables, for example in equation solving. To save
intermediate results while working out some development use names that you
would never use as theoretical symbols; names such as: step1, step2,
testmat, temporary.

2) Always use ClearAll[functionname] before a function definition because in
development one might easily change the lhs argument pattern, leaving old
definitions around. Also clear function names before solving differential
equations because afterwards you may want to define them from the solution.

3) Always have an Initialization Section and load all packages needed in the
notebook there, usually with Initialization cells.

The following is an example of the type of writing we often see in postings
to MathGroup.

a = .5;
b = 3;
f = Exp[-a x] Sin[b x];
Plot[f, {x, 0, 6}]

It works, but is an invitation to problems because one might later forget
that these symbols have values, or where exactly they were set. So clean up
the symbols and write a definition instead that localizes the arguments.

Clear[a, b]

ClearAll[f]
f[a_, b_][x_] := Exp[-a x] Sin[b x]

Plot[f[.5, 3][x], {x, 0, 6}]

Or if one doesn't want to keep specifying the parameters in function calls
because they aren't changed often, write:

ClearAll[f]
With[{a = .5, b = 3},
f[x_] := Exp[-a x] Sin[b x]]

Plot[f[x], {x, 0, 6}]

I apologize for a response that is more elementary than you were probably
looking for but I hope it will be helpful to many new users.

As for having a construction that automatically localized all symbols within
it, I think one would soon find that exceptions were desired, in which case
it is not much more convenient than the present case. Perhaps you meant to
localize all symbols that have a Global context? But then suppose you are
not working in the Global context? One could end up with some complicated
rules as to what is localized. It seems better in localization structures to
specify explicitly what is being localized.


David Park
djm...@comcast.net
http://home.comcast.net/~djmpark/

Virgil Stokes

unread,
Nov 20, 2009, 6:49:17 AM11/20/09
to
These are very useful to document David. I believe that many of us "old
timers" have learned to use these style principles the hard way :-)

--V. Stokes


Nasser M. Abbasi

unread,
Nov 21, 2009, 3:35:10 AM11/21/09
to

hi David;

"David Park" <djm...@comcast.net> wrote in message
news:he36g8$efk$1...@smc.vnet.net...

>
> Clear[a, b]
>
> ClearAll[f]
> f[a_, b_][x_] := Exp[-a x] Sin[b x]
>
> Plot[f[.5, 3][x], {x, 0, 6}]
>

How about also using the above, but also use /. to assign values to
parameters.

Plot[f[a, b][x] /. {a -> .5, b -> 3}, {x, 0, 6}]

You are right, I am finding that if one is very aware and disciplined during
programming Mathematica then can side step many common problems, because in
Mathematica it is more easy to fall into subtle problems for new users than
in other programming languages. If one is slightly sleepy while programming
in Mathematica, then many strange problem will show up later on.

I also wish that Mathematica error handling can be improved in the sense
that when some error shows up in some long running code, that at least it
would tell me on which _line_ the error happened. not just some error
message telling me that I can do this or that.

It seems that, when this happens, I spend more time trying to figure where
the error is coming from because the error message never tells me where this
error is, even though it must have known. It does not even tell me which
function it was in.

If there was an easy to use debugger, I could run the code inside it,
telling it to stop when an error or warning occurs, and this way I know
exactly where the error was. But there is no such thing in Mathematica.
(Please do not tell me to use this so called debugger in Mathematica 7,
under Evaluation, I tried, and have no idea how it is supposed to work).

I hope this error handling improves in next version of Mathematica, and
please make the debugger like a _normal_ and standard debugger is supposed
to be.

May be what we also need is like what David had here, a set of articles that
talks just about good programming styles for Mathematica, or good "patterns"
to follow, targeted to users like most of us, who are not expert Mathematica
programmers. I think this will be very useful.

thanks,
--Nasser


David Park

unread,
Nov 22, 2009, 6:08:56 AM11/22/09
to
Hi Nasser,

Yes rules are a good way to introduce data without setting values to
symbols. This might especially be the case if you are working a problem with
units. You might have something like:

(Problem1Data = {x0 -> 3.25 Meter, v0 -> 5.2 Meter/Second})//Column

then perform symbolic calculations, perhaps using Solve or DSolve, with
equations that contain x0 and v0 and then substitute the data into the
result at the end of the symbolic calculation. Notice that units should be
part of the data and not part of the equations.

result /. Problem1Data

As far a debugging and code development are concerned, I believe most
difficulty occurs by combining too much at once without looking at the
subparts. For me, most routines start out as separate steps in a notebook,
sometimes in one cell and sometimes in separate cells evaluated on a typical
case. I want to see the output and don't use ";" until I'm pretty satisfied
I know what I'm getting. After that, most errors come from failure to
consider special cases.

Only when I've calculated some cases do I try to write a formal definition
and start moving the steps to a Module. There I may only add one step at a
time and repeatedly evaluate to see that any generalizations are working. I
may add Print statements to display intermediate values until I am finished
or I may add them if a problem arises. Sometimes I might set a global temp
variable to some intermediate result, retrieve it from an evaluation, and do
some code development using it as starting data. Mathematica allows one to
do all this simple stuff within a single notebook so why not take advantage
of it? Mathematica is really ideal for this kind of development. Anyway for
me it has worked pretty well and I've never felt the need to study how the
various debuggers work.

Then I might copy a routine to a notebook Routines section (which I call
Package Purgatory) and add a usage statement, SyntaxInformation and other
ancillary definitions. Then after using it for awhile and if it seems
generally useful I may move it to Package Heaven.

From: Nasser M. Abbasi [mailto:n...@12000.org]


hi David;

"David Park" <djm...@comcast.net> wrote in message
news:he36g8$efk$1...@smc.vnet.net...

>


> Clear[a, b]
>
> ClearAll[f]
> f[a_, b_][x_] := Exp[-a x] Sin[b x]
>
> Plot[f[.5, 3][x], {x, 0, 6}]
>

How about also using the above, but also use /. to assign values to
parameters.

Plot[f[a, b][x] /. {a -> .5, b -> 3}, {x, 0, 6}]

You are right, I am finding that if one is very aware and disciplined during

programming Mathematica then can side step many common problems, because in
Mathematica it is more easy to fall into subtle problems for new users than
in other programming languages. If one is slightly sleepy while programming
in Mathematica, then many strange problem will show up later on.

I also wish that Mathematica error handling can be improved in the sense
that when some error shows up in some long running code, that at least it
would tell me on which _line_ the error happened. not just some error
message telling me that I can do this or that.

It seems that, when this happens, I spend more time trying to figure where

the error is coming from because the error message never tells me where this

AES

unread,
Nov 22, 2009, 6:09:17 AM11/22/09
to
> > Clear[a, b]
> >
> > ClearAll[f]
> > f[a_, b_][x_] := Exp[-a x] Sin[b x]

I've seen this more complex form of function definition go by once or
twice in the past, but never used it or learned about it myself.

Pointers to tutorial explanations?

[Or, more challenging, an explanation, in classic "teach a man to fish"
mode, of how a mythical "ordinary user" might go about quickly and
efficiently _finding_ such tutorial explanations, for this specific
case, in Mathematica documentation.]

David Park

unread,
Nov 23, 2009, 7:10:53 AM11/23/09
to
It's called SubValues. One advantage is that it cleanly separates parameters
from variables. Another is that you can write expressions such as:

f[a, b]'[x]

You can also use it conveniently as a postfix operator:

x//f[a, b]

There would be many operations in Mathematica that would be easier to use if
they were defined with SubValues. For example the various
GeometricTransformations are inconvenient in their present form because they
have to be wrapped around a piece of graphics. Postfix operation would be
more convenient. (In Presentations I do provide alternative postfix forms of
all these operators because we always have the primitive form of graphics
available to operate on and it is convenient to define a basic form and then
move it to its proper place.)

But SubValues seems to be the poor orphan of Mathematica "Values". There is
a usage message but no documentation page. I don't know of any tutorial for
it. Command completion for SubValues definitions doesn't give the entire
expression, which I think it should. And DocuTools doesn't handle it
properly. WRI seems to avoid SubValues in any of their basic functions. I
don't know if there is a good reason for this.

You can type SubValues in the DC SEARCH box and then use "Try your search on
all Wolfram sites" to get a fair amount of MathGroup discussion about
SubValues.

The saying is: "Give a hungry man a fish and he'll be back the next day.
Teach a hungry man to fish and you won't see him again for two or three days
- if he hasn't drowned in the meantime."


From: AES [mailto:sie...@stanford.edu]


> > Clear[a, b]
> >
> > ClearAll[f]
> > f[a_, b_][x_] := Exp[-a x] Sin[b x]

I've seen this more complex form of function definition go by once or

0 new messages