20
$\begingroup$

Consider

{x->1}

which has FullForm

List[Rule[x, 1]]

and, therefore,

MatchQ[{x->1}, List[___Rule]]

produces True.

Now consider

<|x->1|>

which has FullForm

Association[Rule[x, 1]]

but

MatchQ[<|x->1|>, Association[___Rule]]

produces False

In fact,

MatchQ[<|x->1|>, Association[___]]

produces False. Any ideas? (I'm trying to make some MathLink xxxxxxxx WSTP functions for serializing C structs as Associations, and this lacuna is messing me up).

$\endgroup$
1
  • $\begingroup$ MatchQ[ Normal @ <|x->1|>, Normal @ Association[ x -> _ ] or MatchQ[ Normal @ <|x->1|>, List[ ___ Rule] ] will work though. $\endgroup$
    – gwr
    Commented Sep 26, 2015 at 14:16

2 Answers 2

19
$\begingroup$

Association is atomic:

<|x -> 1|> // AtomQ
True

Therefore standard pattern matching inside the structure will not work.

You can still match on the implicit head using:

MatchQ[<|x -> 1|>, _Association]
True

There is also AssociationQ:

<|x -> 1|> // AssociationQ
True
MatchQ[<|x -> 1|>, _?AssociationQ]
True

I used the term atomic in a general way meaning an object that does not conform to the standard expression syntax and traversal rules. Taliesin Beynon explains why this is conflating two different concepts in this chat transcript.

$\endgroup$
6
  • 11
    $\begingroup$ It just so happens that Association is currently AtomQ, though I've argued strongly against that fact internally, and I've got SW's say-so that we'll change that eventually. But that doesn't have all that much to do with pattern matching not working inside associations: we all agree it should, it's just hard to do efficiently and we couldn't deliver it for 10. So, to sum up: Association will not be AtomQ forever, and it will support pattern matching eventually. There's a correlation here, not a causation. $\endgroup$ Commented Jul 22, 2014 at 5:33
  • 2
    $\begingroup$ @Taliesin Thanks for the clarification, however I'm afraid I don't understand it. If Assocation objects were standard Mathematica expressions then pattern matching would work by default, would it not? I realize pattern matching could be overloaded for an Atomic object as I believe it is for Complex, but I still think there is causation here. Am I mistaken? $\endgroup$
    – Mr.Wizard
    Commented Jul 22, 2014 at 5:40
  • $\begingroup$ I can see that pattern-matching over the contents of an Association would be difficult. Thanks for the info! $\endgroup$
    – Reb.Cabin
    Commented Jul 22, 2014 at 12:18
  • $\begingroup$ A possibly similar problem arises, for instance, in deciding whether the two JSON objects {a: 1, b: 2} and {b: 2, a: 1} are equal; the problem explodes with size, requiring either some arbitrary sort on the keys or considering $n!$ possibilities (modulo nesting). $\endgroup$
    – Reb.Cabin
    Commented Jul 22, 2014 at 12:25
  • $\begingroup$ @Reb.Cabin, since the sorting is arbitrary can't the data be normalized internally? eg like FullForm[x + 1] == FullForm[1 + x] = Plus[1,x] $\endgroup$ Commented Jul 22, 2014 at 14:07
11
$\begingroup$

In Mathematica 10.4, Association can now be used in pattern matching. Here is the result of the OP's example:

MatchQ[<|x -> 1|>, Association[___Rule]]

True

and

MatchQ[<|x->1|>, Association[___]]

True

There's now also KeyValuePattern which is a pattern object specifically to match elements of an Association or list of rules. Here are some examples:

<|a -> 1, b -> 2, c -> 3|> /. KeyValuePattern[x_ -> 1] :> x

a

Cases[{
  <|"PartOfSpeech" -> "Noun", "Number" -> "Singular"|>,
  <|"PartOfSpeech" -> "Verb"|>},
 KeyValuePattern[{x : "PartOfSpeech" -> y : "Noun"}] :> 
  Association[x -> y]]

{<|"PartOfSpeech" -> "Noun"|>}

$\endgroup$
1

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.