Am 07.02.2011 um 15:52 schrieb Jens Ayton: > On Feb 7, 2011, at 10:52, Fred Kiefer wrote: > >> I remember reading a nice little Macro (or rather two?) that >> encapsulated all the foreach semantics for systems that don't support >> it. This was in David's Objective-C Phrasebook and perhaps David could >> donate that to some Foundation/base header file. That way we will just >> need to keep that header up to date with regards tot eh different >> compilers and anybody could use fast enumerations whenever they are >> supported on their computer without adopting the code. > > For reference, here's what I have now. The actual enumeration macros are > about as hygienic as fake control flow statements can be, at the cost of > requiring the iteration variable to be pre-declared. It requires C99 mode, > but hey, it's 2011. > > > /* Fast enumeration (for (x in y) syntax) is supported in all Mac compilers > when targeting 10.5 or later, and in gcc 4.6 with the GNU libobjc runtime. > At the time of writing, GNUstep stable does not support gcc 4.6, but it > already has support for the fast enumeration protocol in its collection > classes. > > All release versions of clang support fast enumeration, assuming libobjc2 > or ObjectiveC2.framework is being used. We shall make that assumption. > > References: > http://lists.gnu.org/archive/html/discuss-gnustep/2011-02/msg00019.html > http://wiki.gnustep.org/index.php/ObjC2_FAQ > -- Ahruman 2011-02-04 > */ > #if OOLITE_MAC_OS_X > #define OOLITE_FAST_ENUMERATION OOLITE_LEOPARD > #else > #if __clang__ > #define OOLITE_FAST_ENUMERATION 1 > #elif defined (__GNU_LIBOBJC__) > #define OOLITE_FAST_ENUMERATION (OOLITE_GCC_VERSION >= 40600) > #endif > #endif > > #ifndef OOLITE_FAST_ENUMERATION > #define OOLITE_FAST_ENUMERATION 0 > #endif > > > /* Enumeration macros: > foreach(VAR, COLLECTION) enumerates the members of an array or set, setting > the variable VAR to a member on each pass. > foreachkey(VAR, DICT) enumerates the keys of a dictionary the same way. > > Example: > id element = nil; > foreach (element, array) > { > OOLog(@"element", @"%@", element); > } > > These are based on macros by Jens Alfke. > */ > #if OOLITE_FAST_ENUMERATION > #define foreach(VAR, COLLECTION) for(VAR in COLLECTION) > #define foreachkey(VAR, DICT) for(VAR in DICT) > #else > #define foreach(VAR, COLLECTION) for (NSEnumerator *ooForEachEnum = > [(COLLECTION) objectEnumerator]; ((VAR) = [ooForEachEnum nextObject]); ) > #define foreachkey(VAR, DICT) for (NSEnumerator *ooForEachEnum = > [(DICT) keyEnumerator]; ((VAR) = [ooForEachEnum nextObject]); ) > #endif
Looks quite good. Just another idea I would like to propose for discussion is to follow the "bracket-style" of NS_DURING NS_HANDLER & NS_END_HANDLER macros (http://www.cocoadev.com/index.pl?ExceptionHandling) I.e. something like: #define FOREACH(TYPE, VAR, COLLECTION) { NSEnumerator *_e=[(COLLECTION) objectEnumerator]; TYPE VAR; while((VAR = [_e nextObject])) { #define FOREACH_END } } The benefit would be that it appears to be a little more safe against errors than if(i == 0) foreach(...) if(j == 0) ... else ... Finally, I think it should also be possible to rename the internal variable _e by macro name generation so that nested enumerations have private enumerator variables. Something like ... NSEnumerator *_e##VAR; I have not tested this but thought about it for a while. Best regards, Nikolaus _______________________________________________ Discuss-gnustep mailing list [email protected] http://lists.gnu.org/mailman/listinfo/discuss-gnustep
