Re: Mutability
Re: Mutability
- Subject: Re: Mutability
- From: Ondra Cada <email@hidden>
- Date: Wed, 21 Nov 2001 14:57:48 +0100
Vince,
>
>>>>> Vince DeMarco (VDM) wrote at Tue, 20 Nov 2001 15:43:57 -0800:
VDM> There is no way you can tell if a collection is mutable or not. But i
VDM> would argue that you really don't need to know that.
I would beg to differ. Quite often I've encountered a problem solvable
nicely with this pattern:
NSArray *checkAndChangeIfNeeded(id array) { // OpenStep, quite clean and effective
...
if (some_condition) { // need to change
if (![array isKindOfClass:[NSMutableArray class]])
array=[[array mutableCopy] autorelease];
[array addObject:...]; // or insertObject or whatever...
}
...
return array;
}
Now, do you recommend this pattern as obviously wrong? If so, why, and which
one would you recommend to replace it generally?
(If you want a real-life example, the last recent one was with NSStrings: I
needed a function "wrapForeignCharsToHTML", which replaces any foreign
character in a string by the appropriate HTML entity "&#<unichode>;". It
worked exactly this way -- changing mutable strings in place, or making
mutable copies of immutable ones.)
If not, there is a *really* inconvenient problem if [immutableArray
isKindOfClass:[NSMutableArray class]] is YES:
- first, I *have to* make the copy regardless the array I got originally was
mutable or not. That is not particularly memory- and CPU- savvy, especially
in case the arrays are big, and the function happens to be called quite often
on already mutable arrays.
- second, it makes for an unintelligible, clumsy, and error-prone code:
unless I overlooked something, I have to add a boolean variable, this way:
NSArray *checkAndChangeIfNeeded(id array) { // OS X, messy
BOOL alreadyMadeCopy=NO;
...
if (some_condition) { // need to change
if (!alreadyMadeCopy) {
array=[[array mutableCopy] autorelease];
alreadyMadeCopy=YES;
}
[array addObject:...]; // or insertObject or whatever...
}
...
return array;
}
In this simple case the difference is not that big, but if I have more
objects which can be made mutable on-demand, and especially if the
"checkAndChangeIfNeeded" code is complicated enough to be divided into a
number of functions and methods, potentially of more classes, which call one
another, the result becomes *QUITE* messy: I have to make sure the
appropriate BOOL goes to called functions/methods with each object and is
properly tested... The other possibility is to make the mutable copy _always_
whenever a change is made:
NSArray *checkAndChangeIfNeeded(id array) { // OS X, clean but terribly ineffective
...
if (some_condition) { // need to change
array=[[array mutableCopy] autorelease];
[array addObject:...]; // or insertObject or whatever...
}
...
return array;
}
but that might be really unacceptable from the memory and speed point of view...
---
Ondra Cada
OCSoftware: email@hidden
http://www.ocs.cz
2K Development: email@hidden
http://www.2kdevelopment.cz
private email@hidden
http://www.ocs.cz/oc