4 ms·
Objective-C is just, like, a leaky abstraction over C
- bluetomcat 2y agoIt's crappy syntax over a couple of "objc_*" helper functions. One of these functions creates an object, another (objc_msgSend) sends a string called a "selector" and a number of arguments associated with it. The dynamic dispatch happens there – the selector string is mapped to a function address at runtime.
- dfox 2y agoThe 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.
- flohofwoe 2y agoThe 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.
- KMag 2y ago> 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.
- krackers 2y agoDyld (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_explain_Selector_uniquing_in_the_dyld_shared_cache.html https://www.sealiesoftware.com/blog/archive/2009/09/01/objc_... and https://www.mulle-kybernetik.com/weblog/2015/mulle_objc_selectors_are_hashes.html 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/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-runtime-old.mm#L1441-L1468 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.
- deleted 2y ago[deleted]
- mpweiher 2y agoAnd 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.
- mpweiher 2y ago> It's crappy syntax over a couple of "objc_*" helper functions. Exactly! :-) And that's a good thing! Even the keyword syntax in general and Smalltalk syntax specifically...no wonder it gets reinvented. https://blog.metaobject.com/2020/06/the-curious-case-of-swift-adoption-of.html https://blog.metaobject.com/2020/06/the-curious-case-of-swif...
- apple4ever 2y agoI'd say it's an awesome syntax. Much better than Swift for example.
- Klonoar 2y agoAny ObjC project I go back to, I can step into and generally remember what the hell I was doing. This isn’t always the case with Swift, unfortunately. The older I get, the more and more I think ObjC had many things right.
- revskill 2y agoThis article assumed you know objective-c.
- Jaxan 2y agoWhich makes sense, given the title.
- t43562 2y agoI still program in C at times and would love what Objective-C offers in it's place. C++? Not so much because, in essence, that is also a leaky abstraction where you have to care about even more issues. Static versus dynamic methods to give an example: code looks the same but works subtly very differently depending on whether the methods used are static or dynamic. So you cannot ignore how the mechanics of the language works underneath and there is a continuous high mental load. IMO Objective C is simpler - the OO side of it is all dynamic. For performance optimisations you can drop to C and you can really know where you are and what to expect. To be fair I haven't used Objective-C enough so perhaps there are things about it which would turn me off it in the end. I liked Go for example but the way modules work eventually wore me down.
- 3np 2y agoJust curious: What's been stopping you from actually writing more/some of new code in Objective C rather than C?
- klausa 2y agoI can't imagine trying to seriously use Objective-C on non-Apple platforms; even with all of my love and nostalgia for the language. (not the OP)
- ynniv 2y agoGNUStep has never been popular, but it's out there (Aug 2023): https://www.mail-archive.com/discuss-gnustep@gnu.org/msg25501.html https://www.mail-archive.com/discuss-gnustep@gnu.org/msg2550... As you guys know, Algoriddim makes use of GNUstep on Windows. It has just been released in beta: https://www.algoriddim.com/store/djay-windows-beta https://www.algoriddim.com/store/djay-windows-beta
- apple4ever 2y agoYou can use ObjFW https://objfw.nil.im/home https://objfw.nil.im/home pretty easily.
- 2y ago
- bhaak 2y agoI remember a 2 hours debugging session when I started learning Objective-C. I don't remember what I did wrong but I somehow tripped over Objective-C's boolean which isn't a proper type but just a macro of an int value like it is now in C. I did probably something stupid like "if (b != TRUE) {}". What made this so much more infuriating was that if I knew it was just a leaky abstraction over C I wouldn't have made that mistake. But I thought it was on the same level as languages from the Pascal family or Java or any other modern programming language.
- flohofwoe 2y ago> but just a macro of an int value like it is now in C. That's not the case for the last couple of decades (I think since C99?). The underlying type of bool which is defined in stdbool.h is _Bool, which is a "proper" builtin boolean type. The type wrapping in a header is just there to not break existing code which had its own 'bool' typedef. AFAIK in C23, bool is a regular keyword now though.
- bhaak 2y agoThe proper support is still very limited. You can still do "bool b = 10" or "int i = true". C being C ("everything is an int") this will be coerced to 1.
- tuyiown 2y ago> What made this so much more infuriating was that if I knew it was just a leaky abstraction over C I wouldn't have made that mistake. But I thought it was on the same level as languages from the Pascal family or Java or any other modern programming language. Post-rationalization can always blame the tools instead of one owning its own's mistakes. You can blame tools or documentation that omit crucial surprising information or explicitly lies to you. Everything else is assomption you'd better check, or just humbly accept that they will bite you, by definition, in the most unexpected ways.
- mentos 2y agoWhat’s the best example of using Objective-Cs message system at runtime that could not have been achieved at compile time? ChatGPT is giving me contrived examples or examples that could have been achieved with the knowledge of classes at compile time.
- pjmlp 2y agoPortable Distributed Objects in NeXTSTEP. Send a message to an object that is actually proxied over the network to another server. https://en.wikipedia.org/wiki/Portable_Distributed_Objects https://en.wikipedia.org/wiki/Portable_Distributed_Objects
- klausa 2y agoMethod swizzling. Whether that's actually a good feature to have in your language is a different conversation entirely.
- rramadass 2y agoThe inventor of Objective-C, Brad Cox wrote the classic Object-Oriented Programming: An Evolutionary Approach where he defines the concept of "Software-IC" for "Software Component" based systems/design/programming. The underlying C language provides the gate/block-level granular abstractions while the OO features grafted on top provides the chip-level reusability with loose coupling. This is a great mental model to have while programming large systems. The book itself is a classic on how to evolve a language. Brad Cox's above book and Bertrand Meyer's Object-Oriented Software Construction (using the Eiffel language) were my guides to Object-Oriented Design/Programming and Software Engineering in general and i am eternally grateful to them.
- sph 2y agoWhere can I read more about Objective Assembler? Can you go lower level than obj_msgSend? Also bonus points for mentioning the work of Piumarta, whose paper on extensible object models is my all-time favourite and has occupied my mind for years.
- eterps 2y agoI couldn't find info on Objective Assembler either. > Can you go lower level than obj_msgSend? In Oberon you have low-level message sending. See this article that builds in small steps through the various OOP strategies and shows message sending in the last example: https://miasap.se/obnc/data-abstraction.html https://miasap.se/obnc/data-abstraction.html
- meindnoch 2y agoWhich is precisely why it's so powerful.
- deleted 2y ago[deleted]
- albeva 2y agoThe real deal is Obj-C++ - now there is a powerful combo xD For example, we used template wrappers around NSArray for static type checking and "smart pointers" to avoid manual release/retain calls all over the place, which was glorious.
- eadmund 2y ago> You don't program your computer with LISP or Smalltalk. Your computer runs a separate LISP or Smalltalk computer that you can then program on its own terms and in its own world. That’s not really true of all Lisps! Common Lisp may be compiled straight down to assembly (that’s what SBCL does). It can call straight out to the host OS, just like a C program. Now, due to things like garbage collection you have to manage things a bit at the edges, but that’s no different from a language like Go, and I think that no-one would say that Go is its own machine. It’s true of some Lisps, such as Emacs Lisp. Emacs is really a virtual Lisp machine with an editor as a shell. I think that it’s also true of Smalltalk.
- apple4ever 2y agoObjective-C to me is just the pinnacle of language creation. I love plenty of other languages (hello Python) but I just love coding in it so much .