2
$\begingroup$

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.

$\endgroup$
5
  • 1
    $\begingroup$ probably because Pattern and Blank are not in the list of operators, i.e., CNumberQ[y_] evaluates to True? $\endgroup$
    – kglr
    Jul 3, 2019 at 14:22
  • $\begingroup$ 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? $\endgroup$
    – Styg
    Jul 3, 2019 at 14:26
  • $\begingroup$ Samarth, could you post some concrete examples of operators. $\endgroup$
    – kglr
    Jul 3, 2019 at 14:28
  • $\begingroup$ The notebook I'm working with is based on the virasoro.nb notebook here. Everything relevant to my question is unchanged from virasoro.nb $\endgroup$
    – Styg
    Jul 3, 2019 at 17:22
  • $\begingroup$ Samarth, posted the comment as an answer. $\endgroup$
    – kglr
    Jul 3, 2019 at 18:43

1 Answer 1

3
$\begingroup$

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_]
$\endgroup$
4
  • $\begingroup$ 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). $\endgroup$
    – Styg
    Jul 4, 2019 at 16:21
  • $\begingroup$ @Samarth, just use your own list for operators (this was meant as an illustration). $\endgroup$
    – kglr
    Jul 4, 2019 at 16:23
  • $\begingroup$ 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? $\endgroup$
    – Styg
    Jul 4, 2019 at 16:27
  • $\begingroup$ 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]. $\endgroup$
    – kglr
    Jul 4, 2019 at 16:34

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.