4

When using the unsorted version of Complement in this question I met the following unexpected result,

list1 = {a -> b /; c, a -> b, a};
Cases[list1, Alternatives @@ list1]

Out[]={a -> b, a}

Similarly for MatchQ,

MatchQ[Condition[a, b], Condition[a, b]]

Out[]=False

ClearAll@f; SetAttributes[f, HoldAll]; MatchQ[f[x, y], f[x, y]]

Out[]=True

and I need to inactivate Condition in expressions.

How to understand this behaviour?

Lacia
  • 2,253
  • 3
  • 19

2 Answers2

6

Condition[a, b] is pattern that matches a provided b is True. But Condition[a, b] (the first argument to MatchQ) does not match a nor is b true.

Verbatim is designed for expressions which are usually interpreted as patterns.

MatchQ[Condition[a, b], Verbatim[Condition][a, b]]
(*  True  *)
Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • 1
    The same applies to list1. a -> b /; c matches Rule[a, b], provided c is True. It doesn't really matter whether one puts the condition inside or out in this case, i.e., Rule[a, b /; c] or Rule[a, b] /; c. – Michael E2 Jun 16 '22 at 18:45
  • Thx! I never used Verbatim before. Does this function have other usages besides matching rules with rules? – Lacia Jun 18 '22 at 07:20
  • @Lilyric Verbatim can be wrapped around anything that you want to match as literal code and not to function as a pattern. E.g. a_ -> b /. Verbatim[a_] :> x results in x -> b, whereas a_ -> b /. a_ :> x results in x. Sometimes you see it used where HoldPattern would be better expressive of the intent. For instance, the following are effectively equivalent: Verbatim[Integrate][f_, x_], HoldPattern[Integrate][f_, x_], HoldPattern[Integrate[f_, x_]]. The difference is what gets evaluated, but what is evaluated does not change; so they end up matching the same things. – Michael E2 Jun 18 '22 at 13:23
  • I see, thx! Does Verbatim have a partner like Hold vs. ReleaseHold, Inactivate vs. Activate? I read the documentation but hasn't found one. – Lacia Jun 20 '22 at 12:19
  • @Lilyric No, I don't think so. Usually Verbatim is on the pattern-matching side of a rule and does not propagate through a computation. Hold and Inactive are used to stop an expression from evaluation until it reaches a certain step in a computation, at which point ReleaseHold or Activate is needed. HoldPattern is similar to Verbatim in this respect. While ReleaseHold works on it, I don't recall ever doing that. If you need a way to "release" Verbatim, try something like expr /. Verbatim[Verbatim][h_] :> h. – Michael E2 Jun 20 '22 at 14:36
4

To start with, Condition has semantic meaning in Cases/MatchQ:

With[
  {b = True},
  Cases[{Condition[a, b], a}, Condition[a, b]]]
(* {a} *)

That explains why MatchQ[Condition[a, b], Condition[a, b]] returns False. Just for grins, let's try this:

MatchQ[3, 3 /; False]
(* False *)

Now let's work through your first example. A couple of variables to hold our expressions:

list1 = {a -> b /; c, a -> b, a};
alts = Alternatives @@ list1;

Start with something simpler:

Cases[list1, alts[[1]]]
(* {b /; c} *)

What happened? Well, in Cases you can give a rule to actually replace the value that matched. alts[[1]] is a -> b /; c, so we matched on a and replaced it with b/;c. Similarly:

Cases[list1, alts[[2]]]
(* {b} *)

Next, something a bit more complicated:

Cases[list1, alts[[2 ;; 2]]]
(* {a -> b} *)

This time we matched against an Alternatives, not a Rule, so we don't do replacement. However, we did find an exact match.

Okay, moving on again:

Cases[list1, alts[[1 ;; 1]]]
(* {} *)

No matches! We're matching against Alternatives, not Rule, so we should be looking at the whole a -> b /; c expression. The problem is that the Condition still comes into play. Rather than try to explain directly, it's easier to find something that does match:

Cases[{a -> b}, Alternatives[a -> b /; True]]
(* {a -> b} *)

MatchQ[a -> b, a -> b /; True] (* True *)

We're matching the b part as long as the Condition[b, True] is satisfied, which it is by definition. The condition of Condition[b, c] is not satisfied, so we're not matching the b.

Verbatim is used in patterns where you want to match exactly--no transformation or interpretation. So, you could try this:

Cases[list1, Alternatives @@ Verbatim /@ list1]
(* {a -> b /; c, a -> b, a} *)
lericr
  • 27,668
  • 1
  • 18
  • 64