# Unconstrained pattern evaluated by a constrained replacement rule

I'm working with a notebook that defines NonCommutativeMultiply on a defined set of symbols, called operators. Semantically, this is a list of objects that have a noncommutative multiplication (operators on a Hilbert space). It also contains a function CNumberQ that returns true when its argument does not contain any operator.

CNumberQ[expr_] := And @@ (FreeQ[expr, #] & /@ operators);


NonCommutativeMultiply has, as one of its definitions,

x_ ** y_ := x y /; CNumberQ[x] || CNumberQ[y]


Even though the replacement rule is constrained, the following pattern

x_ ** y_


evaluates to

x_ y_


Why does Mathematica apply a constrained replacement rule to a pattern that is unconstrained? I know I can work around this by using HoldPattern, but I could not figure out why this replacement happens by looking at the documentation for rules and patterns.

• probably because Pattern and Blank are not in the list of operators, i.e., CNumberQ[y_] evaluates to True? – kglr Jul 3 '19 at 14:22
• That could be it. The behaviour still seems counterintuitive to me though, given CNumberQ's intended purpose. Perhaps CNumberQ could be redefined to treat pattern arguments properly? I'm a little new to Mathematica, so do you know if this comes under some common design pattern? – Styg Jul 3 '19 at 14:26
• Samarth, could you post some concrete examples of operators. – kglr Jul 3 '19 at 14:28
• The notebook I'm working with is based on the virasoro.nb notebook here. Everything relevant to my question is unchanged from virasoro.nb – Styg Jul 3 '19 at 17:22
• Samarth, posted the comment as an answer. – kglr Jul 3 '19 at 18:43

Using a made-up operator ncm (to avoid unprotecting and making changes to NoncommutativeMultiply)

This replicates the case in OP:

ClearAll[ncm]
operators = {Times, Plus};
CNumberQ[expr_] := And @@ (FreeQ[expr, #] & /@ operators);
x_ ~ ncm ~ y_ := x y /; CNumberQ[x] || CNumberQ[y]
x_~ ncm ~ y_
x_ y_


As expected

 CNumberQ[y_]


True

and adding Pattern in the list operators:

ClearAll[ncm]
operators = {Times, Plus, Pattern};
x_ ~ ncm ~ y_ := x y /; CNumberQ[x] || CNumberQ[y]
x_~ ncm ~ y_
ncm[x_, y_]

• By "operators" in this context I don't mean things like Times and Plus. I mean things that have a noncommutative multiplication (it is clear if one looks at the virasoro.nb notebook, but I'll edit the question accordingly). – Styg Jul 4 '19 at 16:21
• @Samarth, just use your own list for operators (this was meant as an illustration). – kglr Jul 4 '19 at 16:23
• I see. Thanks for the answer! A little follow up: instead of adding Pattern to operators, which would be semantically incorrect, is there a way to supplement the definition of CNumberQ with a special case for a blank or a pattern? – Styg Jul 4 '19 at 16:27
• Samarth, you can use x_ ** y_ := x y /; (CNumberQ[x] || CNumberQ[y]) && FreeQ[{x, y}, Pattern] or define CNumberQ2 as CNumberQ2[expr_] := CNumberQ[expr] && FreeQ[expr, Pattern] and use it instead of CnumberQ, i.e. x_ ** y_ := x y /; CNumberQ2[x] || CNumberQ2[y]. – kglr Jul 4 '19 at 16:34