discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fast enumeration


From: Dr. H. Nikolaus Schaller
Subject: Re: Fast enumeration
Date: Mon, 7 Feb 2011 16:19:25 +0100

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]