14
$\begingroup$

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.

$\endgroup$
2
  • 3
    $\begingroup$ You can use Verbatim: MatchQ[HoldPattern[a[1]], Verbatim[HoldPattern][a[_]]] will return True. $\endgroup$ – user31159 Apr 17 '16 at 18:57
  • 1
    $\begingroup$ @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. $\endgroup$ – vapor Apr 17 '16 at 19:00
11
$\begingroup$

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
]
$\endgroup$
3
  • $\begingroup$ 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! $\endgroup$ – vapor Apr 18 '16 at 3:04
  • 1
    $\begingroup$ @happyfish related: mathematica.stackexchange.com/a/2804/121 :^) $\endgroup$ – Mr.Wizard Apr 3 '17 at 5:02
  • $\begingroup$ @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. $\endgroup$ – vapor Apr 3 '17 at 7:37
2
$\begingroup$

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}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.