Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The message send syntax has one important nuance that you will be hard-pressed to somehow simulate with CPP: the selectors are actually interned so the message dispatch does not compare strings, but pointers. This difference has very meaningful performance impact.


The ObJC runtime C API has functions to convert strings to selectors, which you can do once upfront instead of each time objc_msgSend() is called. AFAIK the ObjC compiler can do this step even during compilation so that no method string names are included in the binary, but I'm not sure.

But I think it's no longer quite correct to describe ObjC as plain syntax sugar over the ObjC runtime C API (same as it is no longer correct to say that C++ is simply a preprocessor for C - AFAIK both ObjC and C++ started as such preprocessors), especially when it comes to features like ARC where the compiler does static lifetime tracking on ObjC object references. I don't think this can be replicated in plain C (and in C++ only less efficiently, since smart pointers are a stdlib feature and oblivious to the compiler).

PS: I actually do like the ObjC syntax. One great feature is that ObjC leaves the C syntax and semantics alone, which means that ObjC automatically supports the latest C standard. C++ would be a much better option today if it went the same route, but instead the 'C subset' in C++ is stuck somewhere ca 1995.


> AFAIK the ObjC compiler can do this step even during compilation so that no method string names are included in the binary, but I'm not sure.

That would be possible for static binaries, but I don't see how that would work for dynamic libraries. Two libraries or a library and the executable would need the strings around in order to ensure they both got the same global address. You could mangle the strings to dynamic symbols so that it's just regular dynamic symbol resolution to get multiple loaded entities to agree on an address, but in that case, the selector string is still present in the binary in mangled form.


Dyld (dynamic linker) does this I think, it's effectively similar to other relocations. Each dynamic library brings its own set of selectors (I just think of them as strings in the data section of the binary, referenced indirectly via a pointer in the objc_selrefs section of the binary which can be updated as needed) and at runtime they're uniqueified.

See https://www.sealiesoftware.com/blog/archive/2009/09/01/objc_... and https://www.mulle-kybernetik.com/weblog/2015/mulle_objc_sele...

I actually can't find much authoritative discussion about this on the internet, just those two posts. But since the objc-runtime is open source, you can probably find it there. I think it might be this method?

https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea...

--

But I'm not sure what GP meant by "at compilation". I suppose the compiler could be smart by reading the selectors of any shared libraries you link against and avoid duplicates in _your_ binary, but that wouldn't work for two shared libraries that know nothing about each other nor anything mapped in via dlopen.


And in fact Brad Cox has stated that it was this at the time crucial optimization that made them go for a full pre-processor instead of just a couple of macros.

Once they had the need for the pre-processor, they decided they might as well make some usable, Smalltalk-derived syntax.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: