8
$\begingroup$

Suppose I have an expression of the form

a b c d + x y z

The FullForm of this is

Plus[Times[a,b,c,d], Times[x,y,z]]

Now suppose I want to set all expressions containing the product b*c to zero. The naive way of doing this is

a b c d + x y z /. Times[___, b, c, ___] -> 0

However, this doesn't work - nothing is replaced.

(Background info: I'm expanding some term using Series, and would like to cancel out all products dx*dy, so that only first-order terms remain.)

Even more confusing: if I don't use Times but a generic function f it works - even when I assign all the attributes of Times to f!

f;
SetAttributes[f, #]& /@ Attributes[Times];
Attributes[f]
f[a, b, c, d] /. f[___, b, c, ___] -> 0

==>
{Flat, Listable, NumericFunction, OneIdentity, Orderless, Protected}
0

(If you evaluate this use a new kernel, as f will be Protected.)

So: how do I replace expressions containing some product*?

*: Assuming the order of the arguments is known. Don't worry about the fact that the expression for b might be on the left of the one for a; solving this would be another question.

$\endgroup$
1
  • $\begingroup$ Feel free to roll back the question title... $\endgroup$
    – Yves Klett
    Dec 3, 2012 at 11:08

2 Answers 2

12
$\begingroup$

Ok, here is the why: patterns do evaluate, just like other expressions. Therefore:

Times[___, b, c, ___]

gives

(*  b c ___^2  *)

even before the pattern-matching is attempted. In this form, the pattern of course does not match. Use HoldPattern to prevent that:

a b c d+x y z/.HoldPattern[Times[___,b,c,___]]->0

(* x y z *)
$\endgroup$
2
  • $\begingroup$ @YvesKlett Yes, because the two named underscores are syntactically different. So, the pattern does evaluate, but no non-trivial transformation (like raising to a power) can be applied,thus it remains valid for the replacement. $\endgroup$ Dec 3, 2012 at 11:17
  • $\begingroup$ just saw the ___^2 part and deleted the comment - reading helps! $\endgroup$
    – Yves Klett
    Dec 3, 2012 at 11:18
2
$\begingroup$

Is this ok ?

expr = a b c d + x y z;
Replace[expr, Times[before___, b, c, after___] -> zero, Infinity] 
(* x y z + zero *)

The main point is that the rest of the factors should be named; this works too :

a b c d + x y z /. Times[before___, b, c, after___] -> 0
$\endgroup$
2
  • $\begingroup$ Can you explain why the named pattern works? $\endgroup$
    – Yves Klett
    Dec 3, 2012 at 10:58
  • $\begingroup$ No, never had this issue, I always put names. I hope the experts will have an explanation. $\endgroup$ Dec 3, 2012 at 11:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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