Andy's Laboratory

Friday, December 29, 2006

 

Syntactic Sugars

I have a sweet tooth for syntactic sugar. I love things like mystring[-1] in Python. Just like real world sugar, too much syntactic sugar can ruin the health of a programmer, but in moderation, it's a wonderful thing.

Naturally, I was overjoyed to learn that Objective-C 2.0 in Leopard will bring property accessors and foreach style loops. This is all good except that in order to take advantage of these 1999 technologies you have to target Leopard. While not a problem for people developing new applications, it's a huge tease for the rest of us.

So what's a programmer to do? Well, at Potion Factory we actually have had accessors and foreach loops for a while now. The solution involves lots of macros and it's of course nothing like what you get with Obj-C 2.0, but it still saves us an enormous amount of typing.

Foreach style loops


After having programmed in Python for a while, I found the following enumeration idiom in Objective-C to be rather painful, to put it mildly.

NSEnumerator *e = [collection objectEnumerator];
id obj;
while (obj = [e nextObject]) {
// do stuff with obj
}

I can't believe it's not butter... or Java...

Luckily I found the following foreach macro somewhere in the cocoa newsgroup.
#define foreach(element, collection) \
for (id _##element##_enumerator = [collection objectEnumerator], element; \
element = [_##element##_enumerator nextObject]; )

It simplifies the enumeration down to the following bit of code
foreach (obj, collection) {
// do stuff with obj
}

More than just taking out two lines of code, this drastically improves the readability., It also saves you from typing the same thing mindlessly over and over throughout the day.

Later on I found out that the foreach macro has been discussed by Jonathan Rentzsch, Michael Tsai, and Wincent Colaiuta. Jonathan has a type-safe version where you specify the object type in the loop to get compiler warnings and Michael's implementation does IMP-caching to speed up calls to -nextObject.

Accessors


// For interface

#define GETTER_H(type, attr, capattr) \
- (type)attr;

#define SETTER_H(type, attr, capattr) \
- (void)set##capattr:(type)value;

#define ACCESSORS_H(type, attr, capattr) \
GETTER_H(type, attr, capattr) \
SETTER_H(type, attr, capattr)

// For implementation

#define MYASSIGN(old, new) \
if (old != new) { \
[new retain]; \
[old release]; \
old = new; }

#define GETTER(type, attr, capattr) \
- (type)attr { return m##capattr; }

#define SETTER(type, attr, capattr) \
- (void)set##capattr:(type)value { MYASSIGN(m##capattr,value); }

#define ACCESSORS(type, attr, capattr) \
GETTER(type, attr, capattr) \
SETTER(type, attr, capattr)

The macros above allows us to define and implement our accessors the following way:
@interface Person : NSObject {
NSString *mName;
}
ACCESSORS_H(NSString*, name, Name);
@end

@implementation Person
ACCESSORS(NSString*, name, Name);
@end

We use various flavors of the above macro and it allows us to develop our applications much faster. Again, it improves readability and eliminates much typing. The (f)ugly part is having to type the variable name in both lowercase and capitalized forms. If you know how that can be avoided, please let me know.

The time savings become quite significant when you apply the idea to Core Data's managed object subclasses.

ManagedObjectAccessors.h

Labels: ,

Comments:
Cool stuff. I have wanted something to automate accessor generation for a long time, but so far have stuck with the relatively painless Accessorizer technique. I have put off building macros such as yours because I feared it would be ugly and have some of the casing issues you allude to.

I have actually leaned more towards the idea of perhaps having a custom-format file that would essentially describe the accessible instance variables. Then a custom compile step could turn those into (transient) +Accessors category sources on the class.

I guess this is roughly what we'll get for free in ObjC 2.0!  
I really liked this. I've always meant to make these macros, so thanks a lot! :)  
Would you believe I actually found you a Buddhist temple near LA that is far enough away from the city but close enough to get to, and has Internet access?

*ahem* *ahem*

Yes I know I'm awesome. Doesn't give you any excuse to not answer my calls!

Andy, are you avoiding me? :( I'm so over losing to you in foosball and air hockey...  
Daniel,

I haven't tried accessorizer but I have heard many good things about it. The downside to the accessorizer approach is that it still produces pages of code when you have a sizable number of accessors, thus reducing readability. The custom preprocessor approach sounds enticing and I think there might be other things it will be useful for as well. Eeeeeenteresting...  
Hi Mary!

Happy new year! :D  
I used to use macros as well until I discovered Accessorizer. But definitely looking forward to properties in Leopard.  
Dont do it!

These macros are horrible things. You may think they're great when you write the code (I saved 7 keystrokes!!!) they're a bugger to maintain.

Use something like Completion Dictionary instead: http://www.obdev.at/products/completion-dictionary/index.html

See also http://blogs.msdn.com/oldnewthing/archive/2005/01/06/347666.aspx for more ranting on the horribleness of these macros.  
For managed objects, you might want to look at Jon Rentzsch's mogenerator.

It autogenerates subclasses for entities, and cleanly separates your handwritten code from autogenerated stuff that can be kept in sync with your model.

He introduces it at http://rentzsch.com/code/mogenerator/. A google for 'site: rentzsch.com mogenerator' will pick up a few later posts, including some more documentation.

-Ken  
"I haven't tried accessorizer but I have heard many good things about it. The downside to the accessorizer approach is that it still produces pages of code when you have a sizable number of accessors, thus reducing readability. "

What about putting your accessors in a category?  
Post a Comment





<< Home

Archives

December 2006   January 2007   June 2007  

Subscribe to posts RSS Feed

About Me

I am the co-founder of Potion Factory, a small Macintosh software company. I like things that are well designed.

See my complete profile

This page is powered by Blogger. Isn't yours?