views:

242

answers:

2

I'm coming from a place without macros (Java/Python/C#/Scala) so perhaps my perspective is distorted but...

Why are macros used in Cocoa? Two that spring to mind are NSLocalizedString and NSAssert (and STAssert). Would it be so hard / unsuitable to make them functions (which could be inlined)? I suppose I find them a little bizarre as an unnecessary throw-back to C (and yes, I am familiar with the pedigree of Obj-C).

Is it just something that was done back in the day or is there a specific reason?

+6  A: 

In general it is preferable to avoid macros, but for functionality like that provided by NSAssert(), you can't.

If you look at the definition, you'll see that it uses __LINE__, __FILE__, _cmd and self from the context it is used in. If it wasn't a macro, it wouldn't have access to that information.

For NSLocalizedString however, i see no obvious reason.

Georg Fritzsche
Very good point!
Joe
I suppose `NSLocalizedString` needs also to access `__LINE__` or `__FILE__` in cases of ambiguity.
Debilski
The Cocoa-version just maps to message passing to `[NSBundle mainBundle]`, so i don't see it. @Deb
Georg Fritzsche
Ok, thanks. It was just a guess.
Debilski
Yes, for `NSLocalizedString` there doesn't seem to be much interesting going on except a function argument re-write.
Joe
NSLocalizedString is actually nice that it is a macro because when defining global NSString const * variables you can initialize them with a value and still get the genstrings exe to translate the names. I have two include files that "turn off/on" the NSLocalizedString that I #include around these global variables or arrays. I have a fairly complex application in 16 different languages and this has been very helpful.
Brent Priddy
@Brent: But you could just as well use a macro `MyLocalizedString` that maps to either of these. I'd say this is less confusing than redefining a Cocoa macro :) Looking into it, it is also documented as a function - so technically i don't think it is guaranteed that it stays a macro.
Georg Fritzsche
+3  A: 

NSLocalizedString is a convenience macro and could probably be made a function.

However, there are good reasons why NSAssert and friends are macros besides the one given in Georg's answer. NSAssert evaluates a boolean expression to determine whether an exception should be thrown. That boolean expression might be quite computationally expensive and not the sort of thing you want to happen in your release code. There's no mechanism in C (and therefore Objective-C) of omitting normal function calls for a release build without resorting to the preprocessor or perhaps using stuff like:

if (debug)
{
    assertAsAFunction(foo == 3, "foo should be 3");
}

Another advantage of the NSAssert macro is that the condition can be stringified for use in a log message.

JeremyP