Construct a pattern with an optional head

How can I construct a pattern that matches both f and h[f] without using the symbol f more than once in the pattern definition? That is, how can I define a pattern pattern that allows for an optional head, and returns {True, True} when used in

MatchQ[pattern] /@ {f, h[f]}

I don't want to use the alternative pattern pattern = f | h[f].

I've tried

pattern = (Identity | h)[f];
MatchQ[pattern] /@ {f, h[f]}
(* {False, True} *)

which matches h[f] but not f; it would only match an unevaluated Identity[f]. Is there a way to evaluate the pattern before application so that Identity[f] becomes f and matches?

• Why is it so crucial to only use f once in the pattern? What's wrong with something like f[_] | Derivative[__][f][_]? You can always use something like With[{symbol = f}, ...] if you want to write f only once. – Sjoerd Smit Mar 28 at 19:35
• Maybe someone knows a trick I don't know, but I don't think you can do this any more elegantly than with Alternatives. I don't know of any way to match an optional head-of-a-head like you're trying to do here. Optional or BlankNullSequence don't work here at least. – Sjoerd Smit Mar 28 at 19:48
• One might be able to do what OP want by leveraging with OneIdentity. – Silvia Apr 1 at 21:08
• I seems to not being able to come up a pattern simple while not matching almost everything. – Silvia Apr 3 at 6:14
• @Silvia the issue seems to be this point in the documentation ("possible issues") of OneIdentity: "In order for f[a] to match a, you must use a pattern that includes Optional." As you say, the resulting pattern then matches almost anything. – Roman Apr 3 at 19:10

I find that Through will make it work:

pattern = Through[(Identity | h)[f]];
MatchQ[pattern] /@ {f, h[f]}
{True, True}

But it works just because in fact Through transforms (Identity | h)[f] into f | h[f].

• That's a start, thanks. I guess I'd like to transform/execute the pattern at match-time, not at define-time; but the idea is there in your solution. – Roman Mar 29 at 6:20
• @Roman With pleasure. If there are more ‘elegant’ approaches, please let me know. – Αλέξανδρος Ζεγγ Mar 29 at 11:13
• I've adopted your solution for the linked problem at mathematica.stackexchange.com/a/194103 – Roman Mar 29 at 11:18
• I know it's not what you are looking for, but pattern := Through[(Identity | h)[f]] doesn't transform at definition time. – mikado Mar 31 at 11:14
• That's right @mikado, but as soon as I use the pattern in a non-delayed setting it gets evaluated right away. For example, define Q[x : Through[(Identity | h)[f]]] = x and then check ?Q: you see that the definition of Q contains the evaluated alternative pattern f|h[f]. – Roman Mar 31 at 17:11

You may use Condition.

MatchQ[a_ /; (Last@Level[a, {-1}] == f)] /@ {f, h[f]}
{True, True}

Or PatternTest

MatchQ[a_?(Not@*FreeQ[f])] /@ {f, h[f]}
{True, True}

Hope this helps.

• These conditional patterns all match too broadly: they'll match all of {f, h[f], g[f], h[h[f]]} etc. Is there a way of constraining them? – Roman Apr 6 at 10:42