11

7

Confusing title, I know. But the question is, if we have two patterns which have the same general structure but different names used in the patterns and different names:

```
a = HoldPattern[f[x_, y_, g_, h_]] :> g[x] + h[y];
b = HoldPattern[g[y_, z_, m_, l_]] :> m[y] + l[z];
```

And I would like to be able to define a pattern for these two pattens, letting {f,x,y,g,h} take arbitrary values. How would I go about this?

To clearify. If I had `a=4;b=5`

. I could define a common pattern through: `_Integer`

and get `MatchQ[a,_Integer](*=>True*)`

and `MatchQ[b,_Integer](*=>True*)`

.

But for my above two patterns, I cannot simply base my pattenr on a and substitute out {f,x,y,g,h} with `_`

eg:

```
badpattern = HoldPattern[f_[Pattern[x_,_], Pattern[y_,_],
Pattern[g_,_], Pattern[h_,_]]] :> h_[x_] + h_[y_];
```

I should not that what I want as a result is a working *pattern* not just a method that accomplishes this. Why? Well because the I would have to reimpliment `MatchQ`

, `Cases`

, `Position`

and so forth for everything that expects a pattern as it's input to still work. The code below accomplishes this, however in an ad-hoc fasion.

This is wrong since the result does not distinguish between structural Blanks, and pattern blanks.

**My initial code**

Just to get a pattern to match to itself I need to get rid of `HoldPattern`

which I do as:

```
MatchQ[a, a /. HoldPattern -> hp_ /; hp === HoldPattern]
(* True *)
```

Of cause I could just use `Verbatim`

however then I won't be able to do the next part. Where I extend the same type of pattern of switching out pattern components such as `HoldPattern`

.

To check `b`

against a pattern based on `a`

, I switch out a collection of heads inject new patterns and condition the pattern on the switched out heads:

```
myPatternPatternA=(a/.{HoldPattern->hp_,Pattern->p_,Blank->b_,RuleDelayed->rd_}
/.{f->f_,x-> x_,y-> y_,g-> g_,h-> h_ }
)/;And[hp===HoldPattern,p===Pattern,b===Blank,rd===RuleDelayed];
MatchQ[b,myPatternPatternA]
(* True *)
```

Note that I'm just using a as a template of the new pattern I construct, in the new pattern `{f,x,y,g,h}`

can all take arbitrary values since I'm injecting a new pattern for them after removing `{HoldPattern,Pattern,Blank,RuleDelayed}`

.

It seems however that I'll occasionally have problems with other symbols, which means I need to extend the list for instance to include `Set`

and `SetDelayed`

, however only when they actually appear in the expression, since otherwise the check fails. As such it feels like a rather cumbersome method. So I'm wondering if others have dealt with such cases and how they have carried this out.

**Update**

I should add that I'm relying on the matching to return values aswell, eg:

```
myPatternPattern = (a/.{HoldPattern->hp_,Pattern->p_,Blank->b_,RuleDelayed->rd_}
/.{f->f_,x-> x_,y-> y_,g-> g_,h-> h_ }
)/;And[hp===HoldPattern,p===Pattern,b===Blank,rd===RuleDelayed]:>f;
Cases[{a,b},myPatternPattern]
(*{f,g}*)
```

Mr. Wizard inquired as to what exactly I mean by the two definitions having the same structure. So I'll clarify. If we have two different expressions: `f[3,4]`

and `g[2,5]`

and I wanted to describe their structure, then I could write `name_[_Integer,_Integer]`

as one possible common structure. When I have two patterns this approach breaks down for obvious reasons, Consider; `_[varA_]`

and `_[varB_]`

. I would like to define a "pattern^2" that matches both of these patterns and assigns varA or varB to a name, so I just follow the same recipe as before and substitute `varA`

in the first with `name_`

and get: ``_[_name_]`

. This obviously fails.
So what I have above is a way to define a pattern for patterns such that I can match elements inside them. Confusing, I know.

1I have a small problem with your specification because

`f =!= g`

. How can these be considered the same? If they are, what else is too? – Mr.Wizard – 2013-01-16T15:32:39.307@Mr.Wizard I don't follow you,

`f`

and`g`

are never considered the same. When matching the pattern`f->f_`

replaces the symbol`f`

with a pattern that (maybe confusingly so) is called`f`

. You could equally well write`f->x_`

and then have`x`

match`f`

and`g`

in each respectively. – jVincent – 2013-01-16T15:36:09.833What you ask for in your update is a pattern analog of so-called parametrized types (exist in ML family of languages, for example). While very interesting and potentially useful thing, this is IMO quite different from your initial question. – Leonid Shifrin – 2013-01-16T15:51:17.230

In your example

`f`

and`g`

are not patterns, they are literals. – Mr.Wizard – 2013-01-16T15:51:20.480@LeonidShifrin My clearification has nothing to do with types, I just chose those, since they are the type of structure you will typically see in a Pattern. I'm editing to remove the unwanted connection. – jVincent – 2013-01-16T15:53:42.440

@Mr.Wizard I substitute the literals for patterns after "breaking apart" other patterns by switching out the heads

`Pattern`

,`Blank`

and such. – jVincent – 2013-01-16T15:56:07.370I swear I'm not trying to be obtuse, but I still don't understand where you specify how

`f`

and`g`

in the two patterns are supposed to be equivalent. – Mr.Wizard – 2013-01-16T15:59:32.863@Mr.Wizard in the 3'rd codebox. I write

`MatchQ[b, (a /. {HoldPattern -> hp_,...} /. {f -> f_,...}) /; And[hp === HoldPattern,...]]`

Now the "f-> f_" replaces the literal`f`

with a pattern. The method goes, 1: break down all patterns, 2: inject new patterns; 3: Verify that all the structure of the broken down patterns is still correct. – jVincent – 2013-01-16T16:14:18.140So you're not trying to check if the two pattern are equivalent, but rather do some transformation using them? – Mr.Wizard – 2013-01-16T16:16:35.740

@Mr.Wizard I'm using my "patterns for patterns" in things such as

`Cases`

, however I wouldn't call that transformations using the patterns. The question is really just about using pattern matching to match things that are themselves patterns. – jVincent – 2013-01-16T16:20:23.113Could you join me in Chat? – Mr.Wizard – 2013-01-16T16:23:57.870

1Have to leave now for today, but my final feeling for all this is that the question is really too vague. There are 3 answers currently, and each interpreted it differently. Unupvoting. – Leonid Shifrin – 2013-01-16T16:31:45.627

@LeonidShifrin I disagree. You seemed to interpret my question correctly, only you didn't fully answer it and you had an initial error which prevented me from getting your method to work, so I posted my own. Mr. Wizard did misinterpret the question, however he seemed to have skipped the part of the question that said

`letting {f,x,y,g,h} take arbitrary values`

, and attempted to answer the question ignoring this part even after some effort on my part to clarify this for him. Having one answer that misinterprets the question is hardly makes it vague. I have attempted to clarify by restructuring. – jVincent – 2013-01-16T21:23:21.200You are free to disagree, as well as I am free to express my opinion :) I fully answered the part which was well-defined, in my opinion. But since you are the one to decide which answer is best for you, all I can say is that IMO the question was vague, and that's what I already did. If at the end you got the information you wanted, that's all that matters at present, but stating question in a more precise fashion would make it easier for us, as well as more useful for future visitors. – Leonid Shifrin – 2013-01-16T23:15:12.553