9
$\begingroup$

The following input:

Cases[{"key" -> Association[]}, HoldPattern["key" -> Association[]]]

Returns {}. Why does it not return {"key" -> Association[]}? I was expecting it to match.

$\endgroup$
5
  • 2
    $\begingroup$ You should use Verbatim for that. HoldPattern is for patterns $\endgroup$
    – RunnyKine
    Apr 19, 2016 at 15:43
  • $\begingroup$ @RunnyKine I thought I would use HoldPattern to treat the rule itself as a pattern, otherwise the rule is interpreted by Cases (as discussed here: mathematica.stackexchange.com/questions/112333/…) $\endgroup$ Apr 19, 2016 at 15:53
  • 6
    $\begingroup$ The subtle point here is that Association[] evaluates to <||>, and even though the FullForms of the two are the same, SameQ on them gives False, because the constructor Association[] does a non-trivial job when evaluated, and the result of it is not a normal expression Association[], but a new atomic object. So, we have Unevaluated[Association[]] === Association[] producing False. Therefore, MatchQ[Association[], HoldPattern[Association[]]] gives False, while of course MatchQ[Association[], HoldPattern[Evaluate@Association[]]] gives True. $\endgroup$ Apr 19, 2016 at 15:58
  • 1
    $\begingroup$ @LeonidShifrin: very interesting. I keep forgetting Association is an atomic expression. But how would you suggest I do the matching with Cases? Inspired by your MatchQ example I can see that Cases[{Association[]}, HoldPattern[Evaluate@Association[]]] matches, but it won't match if the expression containing Association is a Rule. For instance: Cases[{"key" -> Association[]}, HoldPattern["key" -> Evaluate@Association[]]] won't match. $\endgroup$ Apr 19, 2016 at 16:31
  • 3
    $\begingroup$ Use Verbatim, as @RunnyKine suggested. Since it does not prevent evaluation of parts of the pattern, you will then compare evaluated / constructed Association[] in your expression with a similarly evaluated Association[] inside the pattern. Or, much simpler, if you don't care whether or not association is empty, you could use _Association pattern, which is matched in both cases. $\endgroup$ Apr 19, 2016 at 16:39

1 Answer 1

12
$\begingroup$

To answer the question of why there is no match let's look at the output of Trace:

Cases[{"key" -> Association[]}, HoldPattern["key" -> Association[]]] // Trace

(* {{{{Association[], <||>}, "key" -> <||>, "key" -> <||>}, 
  {"key" -> <||>}}, Cases[{"key" -> <||>}, HoldPattern["key" -> Association[]]], {}} *)

We see that Association[] gets evaluated to <||>, which as Leonid states is not a normal expression and so will not match Association[]. As I suggested in the comments, I think the right approach in this and similar situation where an evaluation might occur with Association[], is to use Verbatim:

Cases[{"key" -> Association[]}, Verbatim["key" -> Association[]]]

(* {"key" -> <||> } *)

If you look at the Trace of the expression, you'll see why it matched.

Cases[{"key" -> Association[]}, Verbatim["key" -> Association[]]] // Trace

Verbatim allows its input to also evaluate, hence both expressions now look the same: "key" -> <||>, hence the match. Finally, if for some reason you really want to use HoldPattern, then I suggest wrapping your expression in Unevaluated:

Cases[Unevaluated[{"key" -> Association[]}], HoldPattern["key" -> Association[]]]

(* {"key" -> <||> } *)
$\endgroup$
4
  • $\begingroup$ Thank you. It is quite clear now. $\endgroup$ Apr 19, 2016 at 17:08
  • $\begingroup$ @paideia. You're welcome, glad I could help clarify things. $\endgroup$
    – RunnyKine
    Apr 19, 2016 at 17:16
  • $\begingroup$ Just wondering: how to match _ -> Association[] (using Unevaluated is not an option)? $\endgroup$ Apr 19, 2016 at 17:33
  • 1
    $\begingroup$ @paideia. Unevaluated works for me. Cases[Unevaluated[{_ -> Association[]}], HoldPattern[_ -> Association[]]] $\endgroup$
    – RunnyKine
    Apr 19, 2016 at 17:58

Your Answer

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

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