Re: Scoping and named patterns
- To: mathgroup at smc.vnet.net
- Subject: [mg18213] Re: [mg18132] Scoping and named patterns
- From: "Wolf, Hartmut" <hwolf at debis.com>
- Date: Tue, 22 Jun 1999 20:41:09 -0400
- Organization: debis Systemhaus
- References: <199906180451.AAA22258@smc.vnet.net.>
- Sender: owner-wri-mathgroup at wolfram.com
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] whereas 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
- References:
- Scoping and named patterns
- From: Dr Dan <drdanw@my-deja.com>
- Scoping and named patterns