# How to combine those rules into one? Does something like default values exist for patterns?

I am trying to set up a clever set of rules. Say, I am working symbolically with commutators comm of matrices, where for instance

commRules={
comm[a_+b_,c_]:>comm[a,c]+comm[b,c],
comm[ac_?NumericQ * a_+bc_?NumericQ * b_,c_]:>ac*comm[a,c]+bc*comm[b,c],
};


Since those two rules are moreorless the same (up to the constants ac and bc), I am pretty sure one can combine them into one rule. I was thinking of using something like default arguments for functions, as for instance done in this question and answer - so maybe something along these lines: comm[ac:(_?NumericQ):1 *a_ + b_,c_]:>ac*comm[a,c]+comm[b,c]. Of course, this does not work and ends up throwing an error.

Is it possible to combine the _?NumericQ tests such that I do not have to hard-code each combination of where the constant factors may appear?

To be very clear, I would like to have a SINGLE rule commRule that does e.g. do the follwing

comm[a+b,c]/.commRule
comm[2*a+b,c]/.commRule
comm[2*a+3*b,4*c]/.commRule
(* comm[a,c]+comm[b,c] *)
(* 2*comm[a,c]+comm[b,c] *)
(* 8*comm[a,c]+12*comm[b,c] *)


** Update ** I also unsuccessfully attempted to use BlankNullSequence for this:

comm[a + b, c] /. {comm[a_ + fac2___?NumericQ*b_, c] :> comm[a, c] + fac2*comm[b, c]}
(* comm[a + b, c] *)

• In order to avoid subtle mistakes it is usually better to use a set of simple rules. E.g. commRules={ comm[a_+b_,c_] :> comm[a,c]+comm[b,c], comm[ac_?NumericQ * a_,c_] :> ac*comm[a,c] }; Apr 11, 2017 at 22:59
• @Shadowray Thanks for your input. You're suggesting the usage of ReplaceRepeated in order to split all commutators involving sums into the form comm[a,c] and then check for constants, right? This is my current approach actually, but I am curious if a one-liner exists. Can you please be a bit more specific about the subtle mistakes you're referring to? Apr 11, 2017 at 23:10

Your three examples are met using Optional and the existing Default for Times:

commRule = comm[ac_. a_ + bc_. b_, cc_. c_] :> ac*cc*comm[a, c] + bc*cc*comm[b, c];

comm[a + b, c]       /. commRule
comm[2*a + b, c]     /. commRule
comm[2*a + 3*b, 4*c] /. commRule

comm[a, c] + comm[b, c]

2 comm[a, c] + comm[b, c]

8 comm[a, c] + 12 comm[b, c]


What remains is the additional testing to prevent:

comm[x*a + b, c] /. commRule

comm[b, c] + a comm[x, c]


commRule = comm[ac_. a_ + bc_. b_, cc_. c_] /;
NumericQ[ac] && NumericQ[bc] && NumericQ[cc] :>
ac*cc*comm[a, c] + bc*cc*comm[b, c];


Or in a different style, arguably more or less clean:

commRule = comm[Optional[ac_?NumericQ] a_ + Optional[bc_?NumericQ] b_,
Optional[cc_?NumericQ] c_] :> ac*cc*comm[a, c] + bc*cc*comm[b, c];


Now:

comm[x*a + b, c] /. commRule

comm[b, c] + comm[a x, c]


This might not be what is desired, but it results because the expression a x matches the pattern a_ and a default value of 1 is used for ac_. -- you should clarify how this case should be handled.

• Thank you very much, your last version of commRule is exactly what I was looking for. That a x matches the pattern a is absolutely desired in this case, unless neither a or x have attribute NumericQ. Apr 12, 2017 at 8:58
• @Lukas Glad I could help, and thanks for the Accept. Apr 12, 2017 at 16:29