# What's the point of ContainsAll, ContainsAny and friends?

Mathematica 10.2 contains a few new functions that test set containment: ContainsAll, ContainsAny and a few others. The documentation mentions that these are equivalent to existing functions like IntersectingQ and SubsetQ. The only difference I can see is that the new versions support operator form, but that surely could have been added to the existing functions instead of creating new redundant ones.

• Why do we need these new functions?

• What differences are there between SubsetQ and ContainsAll (whether they seem to warrant the introduction of a new function or not)?

• Moving to the end game of becoming the Turducken of software? I for one cringe seeing built-ins created that are trivial to do with already existing functions and/or add no additional value/capability/performance (often going backward for the latter), while things like probability functionality have languished unimproved. – ciao Jul 15 '15 at 9:20
• @ciao, I'd always joked that Mathematica's logo ought to be a kitchen sink, and it does seem dangerously close to being a ship in danger of sinking from its barnacles. – J. M. will be back soon Jul 15 '15 at 9:32
• The only (rather weak) reason that I can think of is that of readability of code in a given context. Intersections and subsets are phrases from a more mathematically oriented field, whereas I assume lots of people from other disciplines are more comfortable with the more natural English phrases of the Contains* family. – Sjoerd C. de Vries Jul 15 '15 at 11:21
• @ciao @Sjoerd As I understand it, these were primarily added due to their convenience in Entity-related queries (via the operator form). See their respective refpages for examples. – Stefan R Jul 15 '15 at 15:11
• S. Wolfram has something to say about this in his latest blog. Search for "In natural" and read the next two paragraphs from there on. – BoLe Aug 19 '16 at 10:35

I believe Stefan R has given the answer to this question in a comment.

As I understand it, these were primarily added due to their convenience in Entity-related queries (via the operator form). See their respective refpages for examples.

The following notable differences exist between the SubsetQ and ContainsAll:

• ContainsAll has an operator form, SubsetQ doesn't
• ContainsAll has the SameTest option
• ContainsAll handles sparse arrays as normal lists, SubsetQ complains about atomic objects.
• SubsetQ allows any head, ContainsAll doesn't

SubsetQ[f[1,2,3], f[1,2]]
(* True *)

SubsetQ[f[1, 2, 3], g[1, 2]]

During evaluation of SubsetQ::heads: Heads f and g at positions 1 and 2 are expected to be the same.
(* SubsetQ[f[1, 2, 3], g[1, 2]] *)

ContainsAll[f[1, 2, 3], f[1, 2]]
(* ContainsAll[f[1, 2, 3], f[1, 2]] *)

• ContainsAll[association, values] checks for the existence of all values, not key -> value pairs. SubsetQ arguably misbehaves with associations. Demonstration below:

SubsetQ[<|a -> 1, b -> 4|>, <|a -> 1, b -> 4|>]
(* True *)

SubsetQ[<|a -> 1, b -> 4|>, <|a -> 1, c -> 4|>] (* note the different keys *)
(* True *)

SubsetQ[<|a -> 1, b -> 4|>, {1, 4}]

During evaluation of SubsetQ::heads: Heads Association and List at positions 1 and 2 are expected to be the same.

(* SubsetQ[<|a -> 1, b -> 4|>, {1, 4}] *)


ContainsAll does this:

ContainsAll[<|a -> 1, b -> 4|>, <|a -> 1, b -> 4|>]
(* True *)

ContainsAll[<|a -> 1, b -> 4|>, <|a -> 1, c -> 4|>] (* note the different keys *)
(* True *)

ContainsAll[<|a -> 1, b -> 4|>, {1, 4}]
(* True *)


The following similarities exist that are worth pointing out:

• Neither take the multiplicity of elements into account.
• The implementation of both of these functions is a just a couple of lines in top level, hence easy to inspect. It looks like SubsetQ does require the heads to be the same and only operates on the values of associations. It also has an operator form, even though the documentation neglects to mention this as well. – ilian Aug 19 '16 at 21:03