requires: {#Collection. #NoDuplicatesCollection}. provides: {#PredicateCollection}. collections addPrototype: #PredicateCollection derivedFrom: {Collection}. "A collection for which includes: is defined, but iteration and so forth are lazy, allowing for infinite elements. In principle, there should be no duplicates, but this does not make a NoDuplicatesCollection derivation sensible." "TODO: add a protocol for determining the basis context for iteration, such as a collection reification of the image, and some means to override it, structurally, or using subjectively." collections addPrototype: #Aggregate derivedFrom: {PredicateCollection}. Aggregate addSlot: #constituents valued: ExtensibleArray newEmpty. "The collections aggregated." a@(Aggregate traits) flattened [| newA collector | newA: a clone. collector: a constituents newEmpty writer. a constituents do: [| :each | (each is: a) ifTrue: [collector nextPutAll: each constituents] ifFalse: [collector nextPut: each]]. newA constituents: collector contents. newA ]. a@(Aggregate traits) of: collections [| newA | newA: a clone. newA constituents: (collections as: a constituents). newA ]. collections addPrototype: #Union derivedFrom: {Aggregate}. u@(Union traits) includes: obj [ u constituents anySatisfy: [| :each | each includes: obj] ]. p@(PredicateCollection traits) \/ c@(Collection traits) [Union of: {p. c}]. c@(Collection traits) \/ p@(PredicateCollection traits) [Union of: {c. p}]. u@(Union traits) \/ p@(PredicateCollection) [Union of: {u. p}]. p@(PredicateCollection) \/ u@(Union traits) [Union of: {p. u}]. collections addPrototype: #Intersection derivedFrom: {Aggregate}. i@(Intersection traits) includes: obj [ i constituents allSatisfy: [| :each | each includes: obj] ]. p@(PredicateCollection traits) /\ c@(Collection traits) [Intersection of: {p. c}]. c@(Collection traits) /\ p@(PredicateCollection traits) [Intersection of: {c. p}]. u@(Intersection traits) /\ p@(PredicateCollection) [Intersection of: {u. p}]. p@(PredicateCollection) /\ u@(Intersection traits) [Intersection of: {p. u}]. collections addPrototype: #TestCollection derivedFrom: {PredicateCollection}. "A PredicateCollection based on applying a block to the value being tested." TestCollection addSlot: #test valued: [| :_ | True]. "Accept everything by default." t@(TestCollection traits) for: block [| newT | newT: t clone. newT test: block. newT ]. t@(TestCollection traits) includes: obj [ t test applyWith: obj ]. collections addPrototype: #Complement derivedFrom: {PredicateCollection}. "A PredicateCollection based on the negation of the tests for another." Complement addSlot: #basis valued: TestCollection clone. "Contain nothing by default." c@(Complement traits) of: c@(Collection traits) [| newC | newC: c clone. newC basis: c. newC ]. c@(Complement traits) includes: obj [ (c basis includes: obj) not ].