Defined in List.Def
Mixes in with Object
The HasIterator mixin gives its subclasses a way to call functions on each member of a group. It also defines several handy iterators itself, to perform common tasks.
Remember that if the documentation and the software (especially the definition files) disagree, always trust the software.
You will never interact directly with the HasIterator mixin. Instead, you will use objects of classes that inherit from it and define your own subclasses using it.
Instantiate: never Subclass: always Call its methods: sometimes
Class HasIterator defines the following methods:
Method | Description |
---|---|
Iterating | |
Each | Call a function on each member of a group |
Collect | Collect members of the group that meet some criterion/criteria |
CollectUnique | Collect unique members of the group that meet some criteria |
String matching | |
FindByName | Find a member of the group with the given name |
FindByCitation | Find a member of the group with the given citation |
UniqueName | Return a unique name for an object, constructed by appending a number to the end of the name if there are any other objects in a group with the same name |
Whenever you create a subclass using the HasIterator mixin, you must override the following methods:
Method | Description |
---|---|
Each | Call a function on each member of a group |
The HasIterator mixin defines no fields.
operation Each(proc: EachFunction; VAR params: Parameters): Object, noFail, noMethod Call: often Override: always
You must override and implement Each for all subclasses you define that inherit directly from HasIterator.
Call Each when you want to invoke a function repeatedly for every member of your subclass. If you call Each, you must also define the iterative function to be called for each list member, then pass a pointer to this function in the proc parameter. If you want to send any parameters to your iterative routine, pass a pointer to the parameters in params when you call Each.
Each keeps calling the iterative function as long as the iterative function returns nilObject and there are still objects in the list that haven't been processed. When the iterative function returns an object ID, Each stops calling the iterative function and exits. This is useful if you want to stop iterating when your iterative function fulfills some condition, such as successfully completing a search.
The routine that's called for each member of your subclass of HasIterator should be declared like this:
Private ObjectID IterativeProc (ObjectID theObject, void *params)
WARNING! You must use the Private specifier when you declare your iterative function. If you fail to do so, you'll get no warning from any tools during the build process, but your software will fail in an unpredictable way.
The theObject parameter contains the object that's currently being processed. Each passes the params parameter unchanged each time IterativeProc is called.
Here's an example of an implementation of Each, from the HasIndexing mixin:
ObjectID result = nilObject; ulong index, count; if ((count = Count(self)) == 0) return nilObject; BeginImportParameters(params); for (index = 1; index <= count; index++) { ObjectID object; if ((object = At(self, index)) == nilObject || (IsObjectID(object) && !HasObject(object))) continue; if ((result = (*proc)(object, params)) != nilObject) break; } EndImportParameters(params); return result;
operation Collect(collection: ObjectList; function: EachFunction; VAR parameters: Parameters), noFail Call: sometimes Override: rarely
Call Collect to call a function on each object in a group, and add the objects returned by the function to a collection. Collect uses the Each method. The parameter collection
contains the results.
operation CollectUnique(collection: ObjectList; function: EachFunction; VAR parameters: Parameters), noFail Call: sometimes Override: rarely
Call CollectUnique to do the same work as the Collect method, but end up with a list without duplicates. The CollectUnique method does the same thing the Collect method does, but adds only new items to the collection, disallowing duplicates.
operation FindByName(name: String): Object, noFail Call: sometimes Override: rarely
Call FindByName to search for an object with the given name in a group. The FindByName method uses the Each method to compare the name of each object in a group (the result of a GetName call) to the given name string. FindByName returns the first match.
operation FindByCitation(citation: Citation): Object, noFail Call: sometimes Override: rarely
Call FindByCitation to search for an object with the given citation in a group. The FindByCitation method uses the Each method to compare the citation of each object in a group to the given citation. FindByCitation returns the first match.
operation UniqueName(VAR name: String): Boolean, noFail Call: sometimes Override: rarely
Call UniqueName to ensure that an object in a collection has a unique name. UniqueName appends a digit to the name if it isn't unique. UniqueName returns true if it had to change the object's name.
For example, suppose you have an object list called writerList, which looks like this:
Index | Name of list element |
---|---|
1 | Scott |
2 | David |
3 | Scott |
4 | Diane |
5 | CJ |
6 | Scott |
Suppose you define a private iterator function as follows:
typedef struct { Parameters header; ObjectID list; } DoOneNameParams; Private ObjectID DoOneName(ObjectID item, DoOneNameParams *params) { Str255 name; Boolean changed; GetName(item, name); changed = UniqueName(params->list, name); if (changed) SetName(item, name); return nilObject; }
If you then execute the following code:
SetUpParameters(¶meters.header, 1); parameters.list = writerList; Each(theList, (EachFunction)DoOneName, ¶meters.header);
the list will look like this:
Index | Name of list element |
---|---|
1 | Scott1 |
2 | David1 |
3 | Scott2 |
4 | Diane1 |
5 | CJ1 |
6 | Scott3 |