• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Mutability
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


  • Follow-Ups:
    • Re: Mutability
      • From: Gregory Block <email@hidden>
References: 
 >Re: Mutability (From: Vince DeMarco <email@hidden>)

  • Prev by Date: Re: Mutability
  • Next by Date: Re: Mutability
  • Previous by thread: Re: Mutability
  • Next by thread: Re: Mutability
  • Index(es):
    • Date
    • Thread