0
$\begingroup$

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?

See also here.

$\endgroup$
  • 2
    $\begingroup$ 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. $\endgroup$ – Sjoerd Smit Mar 28 at 19:35
  • 2
    $\begingroup$ 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. $\endgroup$ – Sjoerd Smit Mar 28 at 19:48
  • 1
    $\begingroup$ One might be able to do what OP want by leveraging with OneIdentity. $\endgroup$ – Silvia Apr 1 at 21:08
  • 1
    $\begingroup$ I seems to not being able to come up a pattern simple while not matching almost everything. $\endgroup$ – Silvia Apr 3 at 6:14
  • 1
    $\begingroup$ @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. $\endgroup$ – Roman Apr 3 at 19:10
5
+200
$\begingroup$

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].

$\endgroup$
  • $\begingroup$ 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. $\endgroup$ – Roman Mar 29 at 6:20
  • $\begingroup$ @Roman With pleasure. If there are more ‘elegant’ approaches, please let me know. $\endgroup$ – Αλέξανδρος Ζεγγ Mar 29 at 11:13
  • $\begingroup$ I've adopted your solution for the linked problem at mathematica.stackexchange.com/a/194103 $\endgroup$ – Roman Mar 29 at 11:18
  • $\begingroup$ I know it's not what you are looking for, but pattern := Through[(Identity | h)[f]] doesn't transform at definition time. $\endgroup$ – mikado Mar 31 at 11:14
  • $\begingroup$ 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]. $\endgroup$ – Roman Mar 31 at 17:11
1
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ 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? $\endgroup$ – Roman Apr 6 at 10:42

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.