Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

The following works:

In[39]:= ClearAttributes[M, Flat];
Replace[M[F1[a]], M[x_F1] | M[x_F2] -> x]
Replace[M[F2[a]], M[x_F1] | M[x_F2] -> x]
Replace[M[F3[a]], M[x_F1] | M[x_F2] -> x]

Out[40]= F1[a]

Out[41]= F2[a]

Out[42]= M[F3[a]]

the following does not

In[34]:= ClearAttributes[M, Flat];
SetAttributes[M, {Flat}];
Replace[M[F1[a]], M[x_F1] | M[x_F2] -> x]
Replace[M[F2[a]], M[x_F1] | M[x_F2] -> x]
Replace[M[F3[a]], M[x_F1] | M[x_F2] -> x]

Out[36]= M[F1[a]]

Out[37]= M[F2[a]]

Out[38]= M[F3[a]]

why?

share|improve this question
2  
Try adding the OneIdentity attribute as per Flat documentation. –  ssch Jan 19 '13 at 11:51
1  
Related: (304), (5067) –  Mr.Wizard Jan 19 '13 at 12:05
    
@ssch But OneIdentity is wrong. Head should not disappear. –  Suzan Cioc Jan 19 '13 at 12:17
add comment

2 Answers 2

I don't understand why OneIdentity doesn't work for you but this trick appears to work:

SetAttributes[M, Flat];

rule = M[x : Repeated[_F1, {1}]] | M[x : Repeated[_F2, {1}]] :> x;

Replace[M[F1[a]], rule]
Replace[M[F2[a]], rule]
Replace[M[F3[a]], rule]
F1[a]

F2[a]

M[F3[a]]

Please make sure to use RuleDelayed (:>) as I did above when working with named patterns on the right-hand side.

share|improve this answer
add comment

I researched Flat a little bit about a year ago when I wrote this answer. It isn't as clear as can be. It needs updating, and perhaps I'll do that soon. In any case, taking the relevant paragraph:

When the pattern matcher finds itself comparing arguments of an expression whose head (let's call it head) has attribute Flat, it behaves differently: patterns of length one (_, r_, Conditions, PatternTests) trigger the pattern matcher to automatically wrap a head around the respective arguments of the expression so both the expression and the pattern have the same number of arguments (could also be a single argument, but it never leaves it as is. Don't know the purpose). In cases where more than one option is possible due to having __s as arguments, it just starts trying one way and if it doesn't match, tries the next).

In[47]:= ClearAll[f]; SetAttributes[f, {Flat, HoldAllComplete}];
         Cases[Hold@f[1], Hold@f[i_] :> Hold[i], {0}]
         Cases[Hold@f[1, 2, 3, 4], Hold@f[1, i_, 4] :> Hold[i], {0}]
         Cases[Hold@f[1, 2, 3, 4], Hold@f[i_, __] :> Hold[i], {0}]
         Cases[Hold@f[1, 2, 3, 4], 
            Hold@f[i_, j__ /; Length[{j}] === 2] :> Hold[i], {0}]

Out[48]= {Hold[f[1]]}

Out[49]= {Hold[f[2, 3]]}

Out[50]= {Hold[f[1]]}

Out[51]= {Hold[f[1, 2]]}

This case

See this

MatchQ[M[F1[a]], M[_F1]]
MatchQ[M[F1[a]], M[_M]]

(* False *)

(* True *)

The fact that your blank _F1 only matches with head F1 doesn't change the fact that it's a blank, so it actually tries to match M[M[F1[a]]] to M[_F1] and fails. You can use M[F1[___]] to prevent this (or set OneIdentity if appropriate)

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.