CXArray

alpha version, October 2000

The CXArray class represent a generic typeless array, able to contain any other object. Note there is no clumsy limit of all the objects in the array to be of the same type! Therefore, you can easily make eg. recursive arrays, like

(a, (b, c, d), (e, (f, g)))

where the main array has three items, the first being "a", the second an array of three items, and the third being an array of two items. Besides, the second item of the latter nested array is an array itself, containing two items "f" and "g". This possibility--with added benefit of other untyped containers, like the CXDictionary--is extremely handy in many algorithm implementations, which use recursive data, like expression parsing: quite often you don't need to code your own classes for an engine, since the recursive usage of the container types is flexible enough! That, of course, considerably shortens the time needed for design, coding and debugging.

Note also that you do not need to care for the array implementation: it might be "flat" or "segmented" (in the Epoc terminology); the framework selects the optimal implementation itself. There possibly will be an API for the exceptional cases when you might need to force the actual implementation in future (actually, the "flat" array is used currently, for the array stores just the object references, being thus pretty small. Though, that is an implementation issue, and might change anytime without notice).

The array retains any object which is placed into, and releases objects which are removed. That way you never need to worry whether the objects placed once-upon-the-time into an array are still valid: they just are.

Note also that currently arrays are mutable, ie. you can add and remove objects. That will change in future: there will be an immutable class CXArray, and a mutable one CXMutableArray -- that will allow to write considerably more effective code without even thinking (for such services as subarrayWithRange will be able not to alloc anything for immutable arrays, but share the memory directly; that is impossible now).


+CXArray *array;

Returns a newly created empty array.


+CXArray *arrayWithObject(id anObject);

Returns a newly created array, which contains just the one specified object. See also the preprocessor for a nice and easily readable syntax for making arrays.


+CXArray *arrayWithObjects(id anObject,...);

Returns a newly created array, which contains all the objects until a nil. This is probably the most often used constructor; the standard usage looks like

CXArray *a=[CXArray arrayWithObjects:a,b,c,d,nil];

Note that should, say, the variable c contain nil, the array will have just two objects (a and b).

Be cautios not to forget the final nil, for otherwise the creation might work or even crash unpredictably (trying to interpret the addresses which just happen to be on the stack as objects). See also the preprocessor for a nice and easily readable syntax for making arrays.


+CXArray *arrayWithArray(CXArray *array);

Returns a newly created array, which contains all the objects from the argument. For all practical reasons this way you can make a copy of the array.

Note that it does not mean you would make a copies of the contained objects: they will be properly shared by both the arrays.


-id initWithList(VA_LIST argList); // designated initializer

Initializes an array (newly made by the alloc class method) from a variable list of arguments, terminated by a nil. It is actually the same as the following initializer, only the argument list is given as a variable.


-id initWithObjects(id anObject,...);

Initializes an array (newly made by the alloc class method) from all the objects until a nil. All the precautions from the arrayWithObjects class method above apply.


-id initWithObject(id anObject);

Initializes an array (newly made by the alloc class method) with just the one specified object.


-id initWithArray(CXArray *array);

Initializes an array (newly made by the alloc class method) from the array given. See the arrayWithArray class method above.


-int count; // primitive

Returns the number of objects in the array.


-id objectAtIndex(int i); // primitive

Returns the object at the specified index. Raises an exception for an improper index value.


-id lastObject;

Returns the last object in the array. Raises an exception for an empty array.


-int indexOfObject(id anObject);

Returns the index of the first object in the array, which isEqual to the argument. In case there is no such object, returns a value less than zero.


-int indexOfObjectIdenticalTo(id anObject);

Works like the indexOfObject method above, but compares directly the ids of the objects. Therefore, for this method are , say, two different string objects always different regardless their respective contents, whilst the indexOfObject one considers the strings with equal contents equal.


-CXArray *subarrayWithRange(XRange range);

Makes a new array, which contains the objects from the receiver, specified by the range.

CXArray *a=[CXArray arrayWithObjects:@"a",@"b",@"c",@"d",nil];
CXArray *sub=[a subarrayWithRange:XMakeRange(1,2)];

The array sub will contain just the two objects @"b" and @"c".


-CXEnumerator *objectEnumerator;

Returns an array enumerator for easy and convenient sequential access to the objects:

void recursivePrint(id object)
{
  if ([object isKindOfClass:CXArrayClass]) {
    CXEnumerator *en=[object objectEnumerator];
    while ((object=[en nextObject]))
      recursivePrint(object);
  } else printf("%s\n",[[object description] cString]);
}

It is more convenient, considerably more effective, and less error-prone than a classic "for (int i=0;i<array->count();i++)" approach. Which is even more important, the enumerator retains the array; thence it is ensured the array can not be destroyed until you finished the enumeration.

See the CXEnumerator class for more.


-CXString *componentsJoinedByString(CXString *string);

An extremely handy convenience method: it makes a new string object, which contains all the array objects, interposing between each two of them the delimiter string:

CXArray *a=[CXArray arrayWithObjects:@"aa",@"bb",@"cc",nil];
printf("%s\n",[[a componentsJoinedByString:@" and "] cString]);

will print out "aa and bb and cc".

Note there is a counterpart for this method in the CXString class.


-CXArray *sortedArrayUsingFunction(int (*fnc)(id,id));

Returns a new array, which contains the same objects as the receiver, but sorted using the result of the function given. The function is supposed to return a value less than zero if its first argument is less than the second one, a zero if they are equal, and a positive value if its first argument is greater than the second one. A nice mnemotechnis is "presume the arguments are numbers, and put a 'minus' between them".


Mutable arrays

Cutrrently, all the CXArray instances are mutable, ie. you can freely add and remove objects to them. Though as already mentioned above, this is subject to change, in near future there will be two distinct classes: the immutable CXArray, and a mutable CXMutableArray (which will be a subclass of the CXArray, inheriting so all its functionality).

The reason for that is effective object sharing: an immutable array can be "copied" just by returning a reference, whilst a mutable one has to be truly copied (lest it change in future, which would render the copy unuseable).


-void addObject(id anObject);

Adds the object to the end of the array. The object is retained.


-void addObjectsFromArray(CXArray *anArray);

Adds all the objects from the array given in the argument to the end of the receiver.


-void insertObject(id anObject,int index); // primitive

Inserts the object into the array to the given index; the object is retained. Raises an exception for an improper index.


-void deleteObject(int index); // primitive

Removes the object at the given index from the array; the object is released. Raises an exception for an improper index.


-void sortArrayUsingFunction(int (*fnc)(id,id));

Sorts the receiver using the result of the function given. The function is supposed to return a value less than zero if its first argument is less than the second one, a zero if they are equal, and a positive value if its first argument is greater than the second one. A nice mnemotechnis is "presume the arguments are numbers, and put a 'minus' between them".


Copyright © 1999-2000 X.soft, all rights reserved