MathGroup Archive 1999

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Scoping and named patterns

  • To: mathgroup at
  • Subject: [mg18213] Re: [mg18132] Scoping and named patterns
  • From: "Wolf, Hartmut" <hwolf at>
  • Date: Tue, 22 Jun 1999 20:41:09 -0400
  • Organization: debis Systemhaus
  • References: <>
  • Sender: owner-wri-mathgroup at

Hello Doctor,

you've got your posting replied, but let me still add some comment:

Dr Dan schrieb:
> I am having trouble with name conflicts between global symbols and
> named patterns.
> This example from The Book works fine:
> In[1]:= f[a^b] /. f[x : _^n_] -> p[x, n]
> Out[1]= p[a^b, b]
> But if the symbols used as pattern names have values:
> In[3]:= n = 2; x = 3;
>         f[a^b] /. f[x : _^n_] -> p[x, n]
> Out[3]= p[3, 2]
> My usual favorite scoping structure, Module, doesn't help:
> In[4]:= Module[{x, n}, f[a^b] /. f[x : _^n_] -> p[x, n]]
> Out[4]= p[3, 2]
[let me say, there is no such thing as a favorite scoping structure, you
can't freely interchange Module,Block,With,Function...  each of these
has its own precise semantics]

So why the local symbols for x and n (x$... and n$...) haven't been
substituted as Module demands?

The reason is (as stated in S.Wolfram's book and in the on-line help for
Module as well):

"Before evaluating expr, Module substitutes new symbols for each of the
local variables that appear anywhere in expr except as local variables
in scoping constructs."

and Rule is a scoping construct. So (*inside of rule*) x and n are not
substituted, the rhs of Rule takes the values for x and n from the
current environment i.e. x=3, n=2. You can easily observe that
behaviour  when tracing.

> Since local symbols are ignored, it is necessary to use Block:
> In[6]:= Block[{x, n}, f[a^b] /. f[x : _^n_] -> p[x, n]]
> Out[6]= p[a^b, b]
The effect of Block is to effectively clear the variables x and n, so
when the rhs of Rule is executed, x and n remain unbound such that, when
the core of ReplaceAll is executed (a little bit later), and then the
named patterns x and n get there values, these are transfered to p[..]

> This looks like a bug to me.  If I use a symbol in a local context I
> expect the local symbol and never the global.  I am a little concerned
> that the pattern itself doesn't scope its pattern names, that I can
> make one seemingly small change in my notebook and my patterned
> replacements begin crashing.
So there is no bug, Mathematica does, what she's meant to do. But if you
mean to transfer the matched pattern values to the rhs, you have to use
RuleDelayed instead of Rule, as you have learnt already.

But now let me add an observation, which might startle someone:

In[20]:= Module[{y},f[a^b]/.f[x:_^n_]->Block[{y},p[x,n]]]
Out[20]= p[a^b, b]

The global variables for x and n now have *not* been substituted! And
shouldn't Block[{y},p[x,n]] be the same as plain p[x,n]? Since that
ominous variable y isn't referred at all within p? We only have to
recognize: it's not!

So what happend? That variable y within Block[{y},p[x,n]] *is*
substituted through Module (it became y$7 in my case). That means a new
variable (y$7, with unknown value, at that time) is brought into the
scope of Rule. Now in order to keep the semantics of alpha-conversion
for scoping constructs (i.e. the name of the formal variable shall not
matter), x and n become renamed to x$ and n$, and as such at the rhs of
Rule they can no more be bound to an environment variable and they get
there values finally from the (re)named patterns.

It's not decisive to use Block[{y},...] at the rhs of rule, any other
appearance of y will do, e.g.

In[29]:= Module[{y=1},f[a^b]/.f[x:_^n_]->y p[x,n]]
Out[29]= p[a^b, b]

Or even

In[16]:= With[{y=Null},f[a^b]/.f[x:_^n_]->(y;p[x,n])]
Out[16]= p[a^b, b]

It should now be possible to understand, why

In[43]:= (f[a^b]/.f[x:_^n_]->Function[{y},p[x,n]])[1]
Out[43]= p[a^b, b]


In[44]:= f[a^b]/.f[x:_^n_]->Function[{y},p[x,n]][1]
Out[44]= p[3,2]

.....So what is to be learnt? 

The semantics of Rule (lhs -> rhs) and Set (lhs = rhs) is extremly
difficult if the pattern variables appear at the rhs: if the execution
environment contains equally named variables, these are introduced at
the rhs and should therefore not be subjected to alpha-conversion, but
if the execution environment does not contain these variables, they
refer to the named patterns at lhs, and therefore should be
alpha-converted. Obviously it is difficult to maintain this semantics in
deeply nested environments.

So there is a simple rule: avoid that case! *you* can make the semantics
right: give the right unambiguous names to the pattern variables, or
else use RuleDelayed (lhs :> rhs) and SetDelayed (lhs := rhs).

regards, hw

  • Prev by Date: Re: Function definition
  • Next by Date: Re: Function definition
  • Previous by thread: Scoping and named patterns
  • Next by thread: RE: Scoping and named patterns