Re: Flat, OneIdentity attributes

*To*: mathgroup at smc.vnet.net*Subject*: [mg21641] Re: [mg21600] Flat, OneIdentity attributes*From*: Hartmut Wolf <hwolf at debis.com>*Date*: Tue, 18 Jan 2000 02:35:24 -0500 (EST)*Organization*: debis Systemhaus*References*: <200001170343.WAA13401@smc.vnet.net>*Sender*: owner-wri-mathgroup at wolfram.com

Ersek, Ted R schrieb: > > For the most part I understand how Flat and OneIdentity are related and I > demonstrate this using Version 4 in the examples below. > > In the first example (f) has the attributes Flat and OneIdentity. > The pattern matcher treats f[a,2,3] as f[a,f[2,3]] then uses the > replacement rule and {1,{2,3}} is returned. > > In[1]:= > ClearAll[f]; > Attributes[f]={Flat,OneIdentity}; > f[1,2,3]//.f[a_,b_]:>{a,b} > > Out[3]= > {1,{2,3}} > > --------------------------------------------------- > In the next example the only attribute (f) has is Flat. > In this case the pattern matcher treats f[1,2,3] as > f[f[1],f[f[2],f[3]]] then uses the replacement rule and > {f[1],{f[2],f[3]}} is returned. > > In[4]:= > ClearAll[f]; > Attributes[f]={Flat}; > f[1,2,3]//.f[a_,b_]:>{a,b} > > Out[6]= > {f[1],{f[2],f[3]}} > > OneIdentity the pattern matcher doesn't wrap (f) around a single argument > when it tries different ways of nesting (f). > > -------------------------------- > In the next example (f) has the attributes Flat, OneIdentity and the rule is > used. > > In[7]:= > ClearAll[f] > Attributes[f]={Flat,OneIdentity}; > f[2]/.f[n_Integer]:>n+10 > > Out[9]= > 12 > > -------------------------------- > For reasons I can't understand the rule isn't used in the next example. Can > anyone explain why? > > In[10]:= > ClearAll[f] > Attributes[f]={Flat}; > f[2]/.f[n_Integer]:>n+10 > > Out[12]= > f[2] > > --------------------------------------------- > Regards, > Ted Ersek > > For Mathematica tips, tricks see > http://www.dot.net.au/~elisha/ersek/Tricks.html Hello Ted, the answer to your question is given in The Book, Section 2.3.7 p.274 (4th ed.), where it says: In an ordinary function that is not flat, a pattern such as x_ matches an individual argument of the function. But in a function f[a, b, c, ... ] that is flat, x_ can match objects such as f[b, c] which effectively correspond to a sequence of arguments. However, in the case where x_ matches a single argument in a flat function, the question comes up as to whether the object it matches is really just the argument a itself, or f[a]. Mathematica chooses the first of these cases if the function carries the attribute OneIdentity, and chooses the second case otherwise. You can observe that behaviour, if you take a simple test: In[1]:= ClearAll[f]; In[2]:= f[a] /. f[x_] :> h[x] Out[2]= h[a] -- normal case: f[_] matches f with one argument, x_ matches a In[3]:= ClearAll[f]; Attributes[f] = {Flat}; In[5]:= f[a] /. f[x_] :> h[x] Out[5]= h[f[a]] -- now again f[_] matches f with one argument, but x_ matches f[a] because of Attribute Flat (f[a] is converted to f[f[a]] for pattern matching) In[6]:= ClearAll[f]; Attributes[f] = {Flat, OneIdentity}; In[8]:= f[a] /. f[x_] :> h[x] Out[8]= h[a] -- here f[_] matches f with one argument, and x_ matches a_ because of OneIdentity For your example, Ted, you had Plus[x,10] instead of h[x], which doesn't change anything, but you had n_Integer instead of x_ here, so n_Integer could not match f[2] in case of Flat only. The other cases did match obviously. For fun let's look at some other cases: In[9]:= ClearAll[f]; In[10]:= f[f[a]] /. f[x_] :> h[x] Out[10]= h[f[a]] -- ok, clear In[11]:= ClearAll[f]; Attributes[f] = {Flat}; In[13]:= f[f[a]] /. f[x_] :> h[x] Out[13]= h[f[a]] -- because of flatness there can be no difference between this lhs. and simple f[a] as above in Out[5], so again x_ matches f[a] In[14]:= ClearAll[f]; Attributes[f] = {Flat, OneIdentity}; In[16]:= f[f[a]] /. f[x_] :> h[x] Out[16]= h[a] -- again as above, for the same reason What happens with two arguments? In[17]:= ClearAll[f]; In[18]:= f[a, b] /. f[x_] :> h[x] Out[18]= f[a, b] -- no match, obviously In[19]:= ClearAll[f]; Attributes[f] = {Flat}; In[21]:= f[a, b] /. f[x_] :> h[x] Out[21]= h[f[a, b]] -- a match: f[_] to f again with *one* argument. but we have two? No, the lhs. is equivalent to f[f[a,b]] because of flatness and x_ matches f[a,b] In[22]:= ClearAll[f]; Attributes[f] = {Flat, OneIdentity}; In[24]:= f[a, b] /. f[x_] :> h[x] Out[24]= h[f[a, b]] -- OneIdentity is not involved here A variant In[57]:= ClearAll[f]; In[58]:= f[a, f[b]] /. f[x_] :> h[x] Out[58]= f[a, h[b]] -- f[x_] matches f[b] In[59]:= ClearAll[f]; Attributes[f] = {Flat}; In[61]:= f[a, f[b]] /. f[x_] :> h[x] Out[61]= h[f[a, b]] -- f[a,f[b]] is equivalent to f[f[a,b]] In[62]:= ClearAll[f]; Attributes[f] = {Flat, OneIdentity}; In[64]:= f[a, f[b]] /. f[x_] :> h[x] Out[64]= h[f[a, b]] -- same here Interestingly things are somewhat different with BlankSequence[] In[27]:= ClearAll[f]; Attributes[f] = {Flat}; In[29]:= f[a] /. f[x__] :> h[x] Out[29]= h[a] -- f[f[a]] is not tried here, x__ matches directly to a. ReplaceList shows this is the only match. In[35]:= ClearAll[f]; Attributes[f] = {Flat}; In[37]:= f[f[a]] /. f[x__] :> h[x] Out[37]= h[a] -- this match is consistent with Out[29], as it should In[43]:= ClearAll[f]; Attributes[f] = {Flat}; In[45]:= f[a, b] /. f[x__] :> h[x] Out[45]= h[a, b] -- now x__ matches the Sequence[a, b], again consistent with Out[29] In[51]:= ClearAll[f]; Attributes[f] = {Flat}; In[53]:= f[a, f[b]] /. f[x__] :> h[x] Out[53]= h[a, b] -- no surprise In all these test cases here with Pattern[x, BlankSequence[]] there is no difference between Attributes[f] = {Flat} and Attributes[f] = {Flat, OneIdentity} Kind regards, yours Hartmut

**References**:**Flat, OneIdentity attributes***From:*"Ersek, Ted R" <ErsekTR@navair.navy.mil>