.TH "bag" 3 "Oct 12, 2003" .SH Bag .PP .B Inherits from: Cltn .SH Class Description .PP .B Bag instances are unordered sets of objects, with possibly duplicate elements\&. A .B Bag can be thought of, as a .B Set , assigning to each element, a count of how many times that element was added ( .I multiplicity of the element)\&. .PP The multiplicity of a particular element is returned by the .B occurrencesOf: message\&. Repeatedly adding the same (in the sense of .B hash and .B isEqual ) object, simply increases the multiplicity of the element\&. Sending .B remove: messages, will not remove the element until the multiplicity of the element is zero\&. .SH Adding Objects .PP The methods .B add: , .B addNTest: , .B filter: , .B replace: and .B add:ifDuplicate: are used to add objects to a Bag\&. The difference between these methods is the procedure used in adding, how duplicates are handled and what value is returned\&. .SH Difference with OrdCltn .PP Users should realize that, unlike .B OrdCltn , .B Bag does not preserve pointer equality (equality in the .B isSame sense)\&. Bag\&'s instance method .B eachElement will return a sequence of objects, possibly containing duplicate elements, but those so-called duplicates will simply be pointers to the same element\&. Also, since .B Bag is unordered, the order in which elements will be returned, is not the same as the order in which they were added\&. .SH Method types .PP .B Creation .RS 3 .br * new .br * new: .br * with: .br * with:with: .br * add: .br * copy .br * deepCopy .br * emptyYourself .br * freeContents .br * free .RE .PP .B Interrogation .RS 3 .br * size .br * isEmpty .br * eachElement .RE .PP .B Comparing .RS 3 .br * isEqual: .RE .PP .B Adding .RS 3 .br * add: .br * addNTest: .br * filter: .br * add:ifDuplicate: .br * replace: .RE .PP .B Removing .RS 3 .br * remove: .br * remove:ifAbsent: .RE .PP .B Testing Contents .RS 3 .br * includesAllOf: .br * includesAnyOf: .RE .PP .B Adding and Removing Contents .RS 3 .br * addAll: .br * addContentsOf: .br * addContentsTo: .br * removeAll: .br * removeContentsFrom: .br * removeContentsOf: .RE .PP .B Combining .RS 3 .br * intersection: .br * union: .br * difference: .RE .PP .B Converting .RS 3 .br * asSet .br * asOrdCltn .RE .PP .B Using Blocks .RS 3 .br * detect: .br * detect:ifNone: .br * select: .br * reject: .br * collect: .br * count: .RE .PP .B Making elements perform .RS 3 .br * elementsPerform: .br * elementsPerform:with: .br * elementsPerform:with:with: .br * elementsPerform:with:with:with: .RE .PP .B Do Blocks .RS 3 .br * do: .br * do:until: .RE .PP .B Locating .RS 3 .br * find: .br * contains: .br * includes: .br * occurrencesOf: .RE .PP .B Printing .RS 3 .br * printOn: .RE .PP .B Archiving .RS 3 .br * fileOutOn: .br * fileInFrom: .br * awakeFrom: .RE .SH Methods .PP new .RS 1 + .B new .RE .PP Returns a new empty Bag\&. .PP new: .RS 1 + .B new :(unsigned) .I n .RE .PP Returns a new empty Bag, which can hold at least .I n different elements\&. .PP with: .RS 1 + .B with :(int) .I nArgs,\&.\&.\&. .RE .PP Returns a new object with .I nArgs elements\&. For example, .RS 3 id aCltn = [OrdCltn with:2,anObject,otherObject]; .br .RE .PP creates a collection and adds .I anObject and .I otherObject to it\&. In a similar way, .B Set or .B SortCltn instances can be created like this\&. .PP with:with: .RS 1 + .B with : .I firstObject .B with : .I nextObject .RE .PP This method is equivalent to .B with: 2, .I firstObject , .I nextObject \&. .PP add: .RS 1 + .B add : .I firstObject .RE .PP This method is equivalent to .B with: 1, .I firstObject \&. .PP This (factory) method has the same name as the instance method .B add: and can be used as follows, in circumstances when the user does not want to allocate a collection unless it is actually used : .RS 3 aCltn = [ (aCltn)?aCltn:OrdCltn add:myObject ]; .br .RE .PP This shows that creation of the collection is delayed until it is actually needed\&. If the collection already exists, objects are simply added, using the instance method .B add: \&. .PP copy .RS 1 - .B copy .RE .PP Returns a new copy of the Bag\&. .PP deepCopy .RS 1 - .B deepCopy .RE .PP Returns a new copy of the Bag\&. The elements in the new Bag are deep copies of the elements in the original Bag\&. .PP emptyYourself .RS 1 - .B emptyYourself .RE .PP Empties all the members of the Bag (without freeing them)\&. Returns the receiver\&. .PP freeContents .RS 1 - .B freeContents .RE .PP Removes and frees all the members of the Bag, but doesn\&'t free the Bag itself\&. Returns the receiver\&. .PP free .RS 1 - .B free .RE .PP Frees the Bag, but not its elements\&. Returns .B nil \&. Do : .RS 3 bag = [[bag freeContents] free]; .br .RE .PP if you want to free the Bag and its contents\&. .PP size .RS 1 - ( unsigned ) .B size .RE .PP Returns the number of elements in the Bag\&. .PP If an Object was added twice, then .B size returns two, not one, although that the Bag internally stores only one occurence of the Object\&. .PP isEmpty .RS 1 - ( BOOL ) .B isEmpty .RE .PP Whether the number of objects in the Bag is equal to zero\&. .PP eachElement .RS 1 - .B eachElement .RE .PP Returns a sequence of elements in the Bag\&. If the multiplicity of an object in the Bag is greater than one, pointers to the same object will occur multiple times in the Sequence\&. .RS 3 aSeq = [aBag eachElement]; .br while ((anElement = [aSeq next])) { .br /* do something */ .br } .br aSeq = [aSeq free]; .br .RE .PP isEqual: .RS 1 - ( BOOL ) .B isEqual : .I bag .RE .PP Returns YES if .I bag is a Bag, if .I bag has the same number of elements as the receiver, and if each member of the contents of .I bag is contained in the receiver\&'s contents\&. .PP add: .RS 1 - .B add : .I anObject .RE .PP Adds .I anObject to the Bag, and, if it\&'s a duplicate, simply increases the multiplicity of the element\&. This method doesn\&'t inform the caller about whether the Object was a duplicate, because the receiver is always returned\&. .PP addNTest: .RS 1 - .B addNTest : .I anObject .RE .PP Adds .I anObject if it was not previously in the Bag, otherwise increases the multiplicity of the matching element\&. Returns .I anObject if it was not a duplicate, otherwise returns .B nil , but in either case adds the object to the Bag\&. .PP filter: .RS 1 - .B filter : .I anObject .RE .PP The .B filter: method has a special purpose\&. If there is a matching object in the Bag, then .I anObject is freed, the multiplicity of the matching element is increased, and the matching object is returned\&. Otherwise, .I anObject is added and returned\&. .PP add:ifDuplicate: .RS 1 - .B add : .I anObject .B ifDuplicate : .I aBlock .RE .PP Adds and returns .I anObject , if there was no duplicate previously in the Bag\&. .PP Otherwise, this method evalutes .I aBlock and returns the matching object (the object that was already in the Bag)\&. .PP For example, the .B filter: method is equivalent to : .RS 3 [ Bag add: anObject ifDuplicate: { [anObject free] }]; .br .RE .PP replace: .RS 1 - .B replace : .I anObject .RE .PP If a matching object is found, then .I anObject replaces that object, and the matching object is returned\&. If there is no matching object, .I anObject is added to the receiver, and .B nil is returned\&. .PP remove: .RS 1 - .B remove : .I oldObject .RE .PP Removes .I oldObject or the element which matches it using .B isEqual: \&. Returns the removed entry, or .B nil if there is no matching entry\&. .PP .B Note: The .B remove: method of the .B OrdCltn class is implemented to remove an exact match\&. The .B Set class uses a match in the sense of .B isEqual: instead\&. .PP remove:ifAbsent: .RS 1 - .B remove : .I oldObject .B ifAbsent : .I exceptionBlock .RE .PP Removes .I oldObject or the element which matches it using .B isEqual: \&. Returns the removed entry, or return value of .I exceptionBlock if there is no matching entry\&. .PP For example, the method .B remove: is equivalent to : .RS 3 [ aBag remove: oldObject ifAbsent: { nil } ]; .br .RE .PP .B Note: The .B remove: method of the .B OrdCltn class is implemented to remove an exact match\&. The .B Set class uses a match in the sense of .B isEqual: instead\&. .PP includesAllOf: .RS 1 - ( BOOL ) .B includesAllOf : .I aCltn .RE .PP Answer whether all the elements of .I aCltn are in the receiver, by sending .B includes: for each individual element\&. .PP includesAnyOf: .RS 1 - ( BOOL ) .B includesAnyOf : .I aCltn .RE .PP Answer whether any element of .I aCltn is in the receiver, by sending .B includes: for each individual element\&. .PP addAll: .RS 1 - .B addAll : .I aCltn .RE .PP Adds each member of .I aCltn to the receiver\&. If .I aCltn is .B nil , no action is taken\&. The argument .I aCltn need not be a collection, so long as it responds to .B eachElement in the same way as collections do\&. Returns the receiver\&. .PP .B Note: If .I aCltn is the same object as the receiver, a .B addYourself message is sent to the object\&. .PP addContentsOf: .RS 1 - .B addContentsOf : .I aCltn .RE .PP This method is equivalent to .B addAll: and is provided for Stepstone ICpak101 compatibility\&. .PP addContentsTo: .RS 1 - .B addContentsTo : .I aCltn .RE .PP This method is equivalent to .B addAll: , but with argument and receiver interchanged, and is provided for Stepstone ICpak101 compatibility\&. .PP removeAll: .RS 1 - .B removeAll : .I aCltn .RE .PP Removes all of the members of .I aCltn from the receiver\&. The argument .I aCltn need not be a collection, as long as it responds to .B eachElement as collections do\&. Returns the receiver\&. .PP .B Note: If .I aCltn is the same object as the receiver, it empties itself using .B emptyYourself and returns the receiver\&. .PP removeContentsFrom: .RS 1 - .B removeContentsFrom : .I aCltn .RE .PP This method is equivalent to .B removeAll: , and is provided for compatibility with Stepstone ICpak101\&. .PP removeContentsOf: .RS 1 - .B removeContentsOf : .I aCltn .RE .PP This method is equivalent to .B removeAll: , and is provided for compatibility with Stepstone ICpak101\&. .PP intersection: .RS 1 - .B intersection : .I bag .RE .PP Returns a new Collection which is the intersection of the receiver and .I bag \&. The new Collection contains only those elements that were in both the receiver and .I bag \&. The argument .I bag need not be an actual .B Set or .B Bag instance, as long as it implements .B find: as Sets do\&. .PP union: .RS 1 - .B union : .I bag .RE .PP Returns a new Collection which is the union of the receiver and .I bag \&. The new Collection returned has all the elements from both the receiver and .I bag \&. The argument .I bag need not be an actual .B Set or .B Bag instance, as long as it implements .B eachElement: as Sets and Bags do\&. .PP difference: .RS 1 - .B difference : .I bag .RE .PP Returns a new Collection which is the difference of the receiver and .I bag \&. The new Collection returned has only those elements in the receiver that are not in .I bag \&. .PP asSet .RS 1 - .B asSet .RE .PP Creates a .B Set instance and adds the contents of the object to the set\&. .PP asOrdCltn .RS 1 - .B asOrdCltn .RE .PP Creates a .B OrdCltn instance and adds the contents of the object to the set\&. .PP detect: .RS 1 - .B detect : .I aBlock .RE .PP This message returns the first element in the receiver for which .I aBlock evaluates to something that is non-nil \&. For example, the following : .RS 3 [ aCltn detect: { :each | [each isEqual:anObject] } ]; .br .RE .PP Returns .B nil if there\&'s no element for which .I aBlock evaluates to something that non-nil\&. .PP detect:ifNone: .RS 1 - .B detect : .I aBlock .B ifNone : .I noneBlock .RE .PP This message returns the first element in the receiver for which .I aBlock evaluates to something that is non-nil\&. .PP Evaluates .I noneBlock if there\&'s no element for which .I aBlock evaluates to something that is non-nil, and returns the return value of that block\&. For example, .RS 3 [ aCltn detect: { :e | [e isEqual:anObject]} ifNone: {anObject} ]; .br .RE .PP select: .RS 1 - .B select : .I testBlock .RE .PP This message will return a subset of the receiver containing all elements for which .I testBlock evaluates to an Object that is non-nil\&. For example, .RS 3 [ aCltn select: { :each | [each isEqual:anObject] } ]; .br .RE .PP Returns a new empty instance of the same class as the receiver, if there\&'s no element for which .I testBlock evaluates to something that is non-nil\&. .PP reject: .RS 1 - .B reject : .I testBlock .RE .PP Complement of .B select: .PP This message will return a subset of the receiver containing all elements for which .I testBlock evaluates to nil\&. For example, .RS 3 [ aCltn reject: { :each | [each isEqual:anObject] } ]; .br .RE .PP Returns a new empty instance of the same class as the receiver, if there\&'s no element for which .I testBlock evaluates to nil\&. .PP collect: .RS 1 - .B collect : .I transformBlock .RE .PP This message creates and returns a new collection of the same size and type as the receiver\&. The elements are the result of performing .I transformBlock on each element in the receiver (elements for which the Block would return .B nil are filtered out)\&. .PP count: .RS 1 - ( unsigned ) .B count : .I aBlock .RE .PP Evaluate .I aBlock with each of the receiver\&'s elements as the argument\&. Return the number that answered a non- .B nil value\&. .PP elementsPerform: .RS 1 - .B elementsPerform :(SEL) .I aSelector .RE .PP Send .I aSelector to all objects in the collection, starting from the object at offset .I 0 \&. For Stepstone compatibility\&. Producer uses this\&. .PP elementsPerform:with: .RS 1 - .B elementsPerform :(SEL) .I aSelector .B with : .I anObject .RE .PP Send .I aSelector to all objects in the collection, starting from the object at offset .I 0 \&. For Stepstone compatibility\&. Producer uses this\&. .PP elementsPerform:with:with: .RS 1 - .B elementsPerform :(SEL) .I aSelector .B with : .I anObject .B with : .I otherObject .RE .PP Send .I aSelector to all objects in the collection, starting from the object at offset .I 0 \&. For Stepstone compatibility\&. Producer uses this\&. .PP elementsPerform:with:with:with: .RS 1 - .B elementsPerform :(SEL) .I aSelector .B with : .I anObject .B with : .I otherObject .B with : .I thirdObj .RE .PP Send .I aSelector to all objects in the collection, starting from the object at offset .I 0 \&. For Stepstone compatibility\&. ICpak201 uses this\&. .PP do: .RS 1 - .B do : .I aBlock .RE .PP Evaluates .I aBlock for each element in the collection and returns .B self \&. .I aBlock must be a block taking one object (element) as argument; the return value of the block is ignored by this method\&. .PP Often, the Block would, as a side-effect, modify a variable, as in: .RS 3 int count = 0; .br [contents do: { :what | if (what == anObject) count++; }]; .br .RE .PP do:until: .RS 1 - .B do : .I aBlock .B until :(BOOL*) .I flag .RE .PP Evaluates .I aBlock for each element in the collection, or until the variable pointed to by .I flag becomes true, and returns .B self \&. .I aBlock must be a block taking one object (element) as argument; the return value of the block is ignored by this method\&. .PP Typically the Block will modify the variable .I flag when some condition holds: .RS 3 BOOL found = NO; .br [contents do:{ :what | if (what == findObject) found=YES;} until:&found]; .br if (found) { \&.\&.\&. } .br .RE .PP find: .RS 1 - .B find : .I anObject .RE .PP Returns any element in the receiver which .B isEqual: to .I anObject \&. Otherwise, returns .B nil \&. .PP contains: .RS 1 - ( BOOL ) .B contains : .I anObject .RE .PP Returns YES if the receiver contains .I anObject \&. Otherwise, returns NO\&. Implementation is in terms of the receiver\&'s .B find: method (which uses .B isEqual: and .B hash to decide whether the object is contained in the Bag)\&. .PP includes: .RS 1 - ( BOOL ) .B includes : .I anObject .RE .PP This method is equivalent to .B contains: \&. .PP occurrencesOf: .RS 1 - ( unsigned ) .B occurrencesOf : .I anObject .RE .PP Returns the multiplicity of .I anObject in the receiver, i\&.e\&. the number of Objects that are equal (in the sense of .B isEqual to .I anObject ), otherwise returns 0\&. .PP printOn: .RS 1 - .B printOn :(IOD) .I aFile .RE .PP Prints a list of the objects in the Bag by sending each individual object a .B printOn: message\&. Returns the receiver\&. .PP fileOutOn: .RS 1 - .B fileOutOn : .I aFiler .RE .PP Writes out non-nil objects in the Set on .I aFiler \&. Returns the receiver\&. .PP fileInFrom: .RS 1 - .B fileInFrom : .I aFiler .RE .PP Reads in objects from .I aFiler \&. Returns the receiver, which is a Bag that is not yet usable (until the Bag gets the .B awakeFrom: message)\&. .PP awakeFrom: .RS 1 - .B awakeFrom : .I aFiler .RE .PP Rehashes the contents of the Bag, which was previously read from .I aFiler by the .I fileInFrom: method\&. The hash-values of the objects are possibly process or architecture dependent, so they are not stored on the filer\&. Rather, .B awakeFrom: recomputes the values\&.