1
$\begingroup$

Could someone explain to me why

MatchQ[L[1, {3}], L[s_, l___?(FreeQ[#, s_] &)]]

returns False? I would have expected that since 1 is not in {3} the query will be True so that the expressions match. Similarly I find

MatchQ[L[1, {3}], L[s_, l___?(MemberQ[#, s_] &)]]

returns True where I would expect it to be False.

$\endgroup$
5
  • 3
    $\begingroup$ Not an answer, but perhaps L[s_,l_]/;FreeQ[l,s] and L[s_,l_]/;MemberQ[l,s] do what you want. See the documentation for Condition. $\endgroup$
    – user293787
    Commented Oct 14, 2022 at 12:05
  • $\begingroup$ Interesting. I myself didn't notice this before reading this question. Not sure if this is already documented or discussed somewhere, but the named pattern inside PatternTest isn't linked to the named pattern outside. A clearer example: aaa /. expr_?(Function[Print[expr_]; True]) :> bbb, you'll see the printed code is expr_ rather than aaa. $\endgroup$
    – xzczd
    Commented Oct 14, 2022 at 12:25
  • $\begingroup$ First I think ___ should be just _, or it can match a sequence, even an empty one, and it will evaluate FreeQ and MemberQ with unexpected arguments. Second, if s_ is inside PatternTest or Condition it can't be in the same 'pattern scope' as the first s_, that's how these pattern primitives work. So you basically evaluating FreeQ[{3}, _] and MemberQ[{3}, _], and it doesn't matter whether the blank _ has a name or not. If you really want to share a pattern, in this case, I believe L[s_, {Except[s_] ...}] works as expected. $\endgroup$
    – swish
    Commented Oct 14, 2022 at 13:59
  • $\begingroup$ @swish Do you have a reference for the "pattern scope" stuff? $\endgroup$
    – xzczd
    Commented Oct 14, 2022 at 14:09
  • 1
    $\begingroup$ @xzczd Not really, I put it in quotes as it doesn't really exist, it's just what makes sense to me because I reimplemented all of the pattern primitives and have some intuition about them now :). $\endgroup$
    – swish
    Commented Oct 14, 2022 at 14:28

1 Answer 1

1
$\begingroup$

You could try tracing it:

MatchQ[L[1, {3}], L[s_, l___?(FreeQ[#, s_] &)]] // Trace

Result:

{MatchQ[L[1,{3}],L[s_,l___?(FreeQ[#1,s_]&)]],
  {(FreeQ[#1,s_]&)[{3}],
   FreeQ[{3},s_],
   False},
 False}

So, FreeQ[#1,s_]& gets applied to {3}, evalutes it's body, and sure enough, the expression {3} is not free of s_ (which is just effectively _).

Using s_ twice in a pattern means that the pattern should match if the same value is found in both positions. But MatchQ wants to evaluate its pattern argument against the target, and its pattern argument in this case involves a PatternTest. It's going to interpret that PatternTest as part of what it needs to evaluate to determine a match, it's not going to interpret it as something to "see" in the target argument.

I obviously don't know what problem you're trying to solve, but this looks very convoluted. You're using MatchQ, which uses patterns, but you're feeding it a pattern whose only meaningful semantic is a predicate. But in turn, that predicate uses FreeQ, which uses patterns. Why not reduce the layers of indirection?

FreeQ[#[[2]], #[[1]]] &[L[1, {3}]]
(* True *)
$\endgroup$
6
  • $\begingroup$ "so it's holding its arguments until it gets applied" Hmm... I don't think the Hold* attribute is relevant. Try ClearAttributes[Function, HoldAll]; ClearAttributes[PatternTest, HoldRest]; aaa /. expr_?(Function[aaa === expr_]) :> bbb $\endgroup$
    – xzczd
    Commented Oct 14, 2022 at 15:32
  • $\begingroup$ Okay, backing up, the function is either a predicate being used by the pattern, or it's explicitly part of the pattern itself. In other words, OP seems to expect s_ to be bound to a value when evaluating the function. But s_ will only be bound to the value that it matches within the expression. There is no FreeQ/Function stuff in the L expression that we're trying to match. The semantics, the way OP wrote it, would be, "match an expression whose first element is also identitcal to a sub-expression that you'll find in a Function deep inside the second element"... $\endgroup$
    – lericr
    Commented Oct 14, 2022 at 15:39
  • $\begingroup$ So, I agree that the hold attribute isn't really relevant. What was in my head was that some function was being evaluated as part of matching l___, and there is no reason to expect that the body of that function to be "computed" in real time, so to speak. I'll update my answer. $\endgroup$
    – lericr
    Commented Oct 14, 2022 at 15:41
  • $\begingroup$ As to the "funny story" part, I'm afraid you've misunderstood something… That sample is actually equivalent to MatchQ[L[1, {3}], L[s_, l___?(FreeQ[#1, ssss] &)]]. Scoping is not relevant here. $\endgroup$
    – xzczd
    Commented Oct 14, 2022 at 16:49
  • $\begingroup$ OMG. Okay, notes to self: (1) don't try to answer SE questions in the moments before you need to leave the house; (2) take some time to figure out how pattern matching f-ing works. $\endgroup$
    – lericr
    Commented Oct 14, 2022 at 21:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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