14

My original problem is to delete all rules starts with a[1] from SubValues[a]

For example,

{HoldPattern[a[1][2]] :> 1, HoldPattern[a[2][3]] :> 5, 
 HoldPattern[a[1][x_, y_]] :> x + y, 
 HoldPattern[a[2][x_, y_]] :> x - y, HoldPattern[a[2][x_]] :> x}

would become

{HoldPattern[a[2][3]] :> 5, HoldPattern[a[2][x_, y_]] :> x - y, 
HoldPattern[a[2][x_]] :> x}

I tried to use patterns at first, but I found that when matching patterns with HoldPattern head, results become unpredictable.

I found 2 general pattern matching results with HoldPattern I don't understand (doc on HoldPattern and related did not say anything on this):

1.MatchQ[HoldPattern[a[1]], HoldPattern[_[_]]] is True, but include some names, and MatchQ[HoldPattern[a[1]], HoldPattern[a[_]]] is False.

2.MatchQ[HoldPattern[a[1]], HoldPattern[_[_]]] is True, but MatchQ[HoldPattern[a[1][1]], HoldPattern[_[_][_]]] is False.

I solved my problem with

FilterRules[SubValues[a], _?(FreeQ[#, name] &)]

But I would still like to know about matching HoldPattern expressions.

MarcoB
  • 67,153
  • 18
  • 91
  • 189
vapor
  • 7,911
  • 2
  • 22
  • 55
  • 3
    You can use Verbatim: MatchQ[HoldPattern[a[1]], Verbatim[HoldPattern][a[_]]] will return True. –  Apr 17 '16 at 18:57
  • 1
    @Xavier can you explain more? I only know how Verbatim work with blanks, and I have no idea what HoldPattern did to the expression that caused this mismatch. – vapor Apr 17 '16 at 19:00

2 Answers2

11

Clarification of HoldPattern usage:

HoldPattern[expr] is equivalent to expr for pattern matching, but maintains expr in an unevaluated form.

I think this can be ambiguous for beginners. One could think that what we are doing in

MatchQ[HoldPattern[a[1]], HoldPattern[_[_]]] 

is to more or less

MatchQ[ a[1], _[_] ] 

where both arguments are kept unevaluated. That's not the case. "for pattern matching" from the usage message means "when used in pattern". And here a pattern is the second argument.

Knowing that we can easily explain your examples:


So, case 1,

MatchQ[HoldPattern[a[1]], HoldPattern[_[_]]]

is really trying to match _[_] to HoldPattern[a[1]], with success because it really is (HoldPattern)[(a[1])].

Furthermore, it will fail to match a[_] because this represents an expression which outer head is a while it should be HoldPattern.


Case 2 can be explained this way too. When the HoldPattern is stripped, _[_][_] doesn't match HoldPattern[a[1][1]] as it really is _[_[_][_]]:

MatchQ[HoldPattern[a[1][1]], HoldPattern[_[_[_][_]]]]
True

Possible issues with Verbatim:

To prevent HoldPattern from being stripped you can use Verbatim. But it can't be used mindlessly. E.g. let's say you have defined:

a[_]:=2

This will create

HoldPattern[a[_]] :> 2

down value. As discussed your approach won't work:

MatchQ[ HoldPattern[a[_]] :> 2, HoldPattern[a[_]] :> 2 ] (*False*)

but also

MatchQ[ HoldPattern[a[_]] :> 2, Verbatim[HoldPattern][a[_]] :> 2 ]

fails because there isn't anything preventing a[_] from evaluating to 2.

Here we are safe:

MatchQ[
 HoldPattern[a[_]] :> 2,
 Verbatim[HoldPattern][a[_]] :> 2 // HoldPattern
]

The answer finally:

DeleteCases[
 values,
 _[a[1][__]] :> _ // HoldPattern
]
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
Kuba
  • 136,707
  • 13
  • 279
  • 740
  • That's exactly what I misunderstood, you even gave me an answer to the "preventing pattern from evaluated" problem I actually encountered but didn't mention. Thanks! – vapor Apr 18 '16 at 03:04
  • 1
    @happyfish related: http://mathematica.stackexchange.com/a/2804/121 :^) – Mr.Wizard Apr 03 '17 at 05:02
  • @Mr.Wizard nice! Sometimes evaluation control is beyond my usual problem solving logic, and I'll end up with a pile of spaghetti code. The answers from you and a few others on this topic are always eye opening. – vapor Apr 03 '17 at 07:37
2

My go to method for handling *Values is to just use _ everywhere. So, I would use:

values = {HoldPattern[a[1][2]] :> 1, HoldPattern[a[2][3]] :> 5, 
    HoldPattern[a[1][x_, y_]] :> x + y, 
    HoldPattern[a[2][x_, y_]] :> x - y, HoldPattern[a[2][x_]] :> x};

DeleteCases[values, _[_[a[1][__]],_]]

{HoldPattern[a[2][3]] :> 5, HoldPattern[a[2][x_, y_]] :> x - y, HoldPattern[a[2][x_]] :> x}

Carl Woll
  • 130,679
  • 6
  • 243
  • 355