Re: Re: Scoping and named patterns
- To: mathgroup at smc.vnet.net
- Subject: [mg18202] Re: [mg18173] Re: Scoping and named patterns
- From: "Wolf, Hartmut" <hwolf at debis.com>
- Date: Mon, 21 Jun 1999 22:50:42 -0400
- Organization: debis Systemhaus
- References: <7kcjrn$lql@smc.vnet.net> <199906200354.XAA27517@smc.vnet.net.>
- Sender: owner-wri-mathgroup at wolfram.com
Hello Doctor, I'd like to still give a little comment: Dr Dan schrieb: > > In article <7kcjrn$lql at smc.vnet.net>, > Dr Dan <drdanw at my-deja.com> wrote: > > 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] > > > > This shows that the global symbol is used as the pattern name and not > > the symbol local to the scoping construct: > > > > In[5]:= Module[{x, n}, Clear[x, n]; f[a^b] /. f[x : _^n_] -> p[x, n]] > > Out[5]= p[3, 2] > > > > 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] > > > > 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. > > > > Any comments, or a better workaround than Block? > > Just after posting the above message, I discovered that the Block > solution doesn't always work. My original intent was to store a > complicated rule for use elsewhere in the notebook: OK, then you have to be cautious *twice*, first when your rule is being defined, second, when it is evaluated > > In[1]:= n = 2; x = 3; > In[2]:= r = Block[{x, n}, f[x : _^n_] -> p[x, n]]; > f[a^b] /. r > Out[3]= p[3, 2] > > Oops. Now my replacement is outside the block. ...... Yes, but the defintion of your rule too! To understand that, better do single steps! If you define In[4]:= r1=f[x:_^n_]->p[x,n]; In[5]:= ?r1 "Global`r1" r1 = f[x:_^(n_)] -> p[3, 2] This is to be understood well: at time of definition the actual values for x and n are substituted at the rhs of Rule. But if you do In[7]:= r2=Block[{x,n},f[x:_^n_]->p[x,n]]; In[8]:= ?r2 "Global`r2" r2 = f[x:_^(n_)] -> p[3, 2] You do get the *same*, why? Trace will show: Block indeed returns unsubstituted values for x and n (since they are effectively cleared inside Block), but the result of Block is then evaluated again *before* r2 is set, and such the values of x and n creep in again. You'll get your wanted rule if you Set *inside* of Block: In[11]:= Block[{x,n},r3=f[x:_^n_]->p[x,n]] Out[11]= f[x : _^n_] -> p[3, 2] In[13]:= ?r3 "Global`r3" r3 = f[x:_^(n_)] -> p[x, n] Now if you try In[31]:= f[a^b]/.r3 Out[31]= p[3,2] you still don't get what you wanted. Again Trace will show you why: the rhs of Rule r3 will be evaluated, before the pattern variables match, and such 3 and 2 again come in still too early. But if you also evaluate your rule inside Block, then In[33]:= Block[{x,n},f[a^b]/.r3] Out[33]= p[a^b, b] > .....Then I stumbled upon > the correct solution (without knowing why it worked), using RuleDelayed: > > In[4]:= r = f[x : _^n_] :> p[x, n]; > f[a^b] /. r > Out[5]= p[a^b, b] > x_x > This seems to be a robust solution. Read the other postings in this > thread for a much better explanation than I can give. Thank you for > the help. This is (mostly) the better way to do it, and there will be no evaluation of x or n until the pattern variables are defined within the scope of Rule, when it is applied. So there should be no need to do that doubled Block-ing. However, when p[x,n] ist some complicated or costly expression, it may be advantageous to evaluate it (once) at definition time, instead of (possibly, over and over) when the rule is applied. So with In[80]:= zzz:=Do[Tan[ArcTan[Sqrt[Pi]]],{10000}] In[81]:= zzz//Timing Out[81]= {2.574 Second,Null} In[82]:= q[x_,n_]:=(zzz;p[x,n]) compare In[83]:= (rx=f[x:_^n_]:>q[x,n])//Timing Out[83]= {0. Second, f[x : _^n_] :> q[x, n]} In[84]:= f[f[a^b]^f[c^d]]//.rx //Timing Out[84]= {10.455 Second, p[p[a^b, b]^p[c\^d, d], p[c^d, d]]} to In[85]:= Block[{x,n},ri=f[x:_^n_]->q[x,n]]//Timing Out[85]= {2.583 Second, f[x : _^n_] -> p[3, 2]} In[86]:= Block[{x,n},f[f[a^b]^f[c^d]]//.ri ]//Timing Out[86]= {0. Second, p[p[a^b, b]^p[c\^d, d], p[c^d, d]]} But perhaps still the better way to do that would be: In[91]:= Block[{x,n},rx2=f[x:_^n_]:>Evaluate[q[x,n]]]//Timing Out[91]= {2.604 Second, f[x : _^n_] :> p[x, n]} In[92]:= f[f[a^b]^f[c^d]]//.rx2 //Timing Out[92]= {0. Second, p[p[a^b, b]^p[c^d, d], p[c^d, d]]} Again you have to be careful to wrap the whole definition of rule rx2 within Block! But you'll need no Block-ing at rule application. Regards, hw
- References:
- Re: Scoping and named patterns
- From: Dr Dan <drdanw@my-deja.com>
- Re: Scoping and named patterns