The following input:

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

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

  • 2
    $\begingroup$ You should use Verbatim for that. HoldPattern is for patterns $\endgroup$ – RunnyKine Apr 19 '16 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$ – rmagno Apr 19 '16 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$ – Leonid Shifrin Apr 19 '16 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$ – rmagno Apr 19 '16 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$ – Leonid Shifrin Apr 19 '16 at 16:39

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

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.