I need to match a products with exactly one factor F
, an arbitrary number of factors of head A
, and possibly additional inert factors. I'm having trouble writing one pattern that can capture all the following cases.
I tried the following rule (the c
term is there for show)
rule1 = Times[ayes___A, F] :> func[Times[ayes], F];
c + F /. rule1
c + A[x] F /. rule1
c + A[x] A[y] F /. rule1
c + d A[x] A[y] F /. rule1
c + F (*desired: c + func[1,F] *) c + func[A[x], F] (*correct*) c + func[A[x] A[y], F] (*correct*) c + d func[A[x] A[y], F] (*correct*)
The first expression failed to properly match, because it doesn't have head Times
. Then I tried a second rule with Optional
:
rule2 = rule2 = Times[Optional[ayes__A], F] :> func[Times[ayes], F];
(*Input same as above but with /. rule2*)
c + func[1,F] (*correct*) c + func[A[x], F] (*correct*) c + func[A[x] A[y], F] (*correct*) c + d A[x] A[y] func[1, F] (*desired: c + d func[A[x] A[y], F] *)
This time the fourth expression failed to match because of the extra factor. So now I try a third rule to accommodate that extra factor:
rule3 = Times[extra_. Optional[ayes__A], F] :> extra*func[Times[ayes], F]
(*Input same as above but with /. rule3*)
c + func[1,F] (*correct*) c + func[A[x], F] (*correct*) c + A[y] func[A[x], F] (*desired: c + func[A[x] A[y], F]*) c + d A[y] func[A[x], F] (*desired: c + d func[A[x] A[y], F] *)
Now the pattern matcher got confused probably because of all the optional arguments.
Is there a single pattern that can match all these cases? Since I'm working with potentially large expressions, I would also prefer to avoid using pattern tests (Conditional
) for performance reasons.
Times[a_. ayes__A, F] | a_. F :> a func[Times[ayes], F]
? $\endgroup$c + A[y] func[A[x], F]
$\endgroup$Alternatives
is the way to go, although I'm not sure if it has the same performance hit as using pattern tests. For instance,rule1 = Times[ayes__A, F] | Times[a_ ayes__A, F] | a_. F :> a func[Times[ayes], F];
. $\endgroup$