To argue that Objective-C resembles a metaphysically divine language, or even a good language, is like saying Shakespeare is best appreciated in pig latin. Objective-C is, at best, polarizing. Ridiculed for its unrelenting verbosity and peculiar square brackets, it is used only for building Mac and iPhone apps and would have faded into obscurity in the early 1990s had it not been for an unlikely quirk of history. Nevertheless, in my time working as a software engineer in San Francisco in the early 2010s, I repeatedly found myself at dive bars in SoMa or in the comments of HackerNews defending its most cumbersome design choices.
↫ Gabriel Nicholas at Wired
I’ll just step back and let y’all handle this one.
I can objectively (ahem) state that Objective C is one ugly language. That square bracket notation is just the icing
Well, this is just my topic 🙂
A lot of people hate the language, but this hate mostly comes from it being different and not what people expect. The syntax is weird at first, because it isn’t C++ syntax, but Smalltalk. However, once you get over it, you start to notice the beauty in the language and how powerful it is – and at that point, you also get familiar with the syntax and no longer hate it. Everybody hated it at first, me included, but it’s just because it’s different and you’re not used to it. Inserting the arguments into the message name, the most confusing thing at first, actually makes for surprisingly readable and self-describing code once you’re used to it. You need to read the documentation far less than in other langagues, and usually you read code more than you write it – plus every editor has code completion.
Most people got into Objective-C because they own Apple hardware. For me, it was actually the opposite: I found Objective-C in GCC and liked the langauge so much that I started https://objfw.nil.im/. Only later did I acquire Apple hardware to see how Objective-C is there. The language just has a feature set that no other language provides, making it one of the most versatile languages: I can write my code in Objective-C as highlevel as in a scripting language due to the dynamic dispatch while still having a type system and while still having excellent performance (a dynamic dispatch in Objective-C costs roughly as much as a virtual call in C++, at least with my own runtime). I can also write plain C code in Objective-C or interfacing with existing C code without needing any bindings. Or I can use Objective-C++ and do the same with C++ in Objective-C instead of C. And if I absolutely need the best performance possible, I can always drop down to assembly. No other language allows you to write such highlevel and lowlevel code at the same time. And all the while writing software that is *much* more portable than the modern languages like Rust or Go.
It’s just sad to me that the language never caught on outside of the Apple ecosystem. I did try to change that by creating ObjFW, which now also makes it an excellent language to for all kinds of things, e.g. write performant server software, or Linux client software, or even a kernel if you want to, however, a lot of people are just immediately dismissing Objective-C as “that Apple language” and never really look into – and/or never get to the point of being willing to try something with a different syntax than they’re used to.
js,
Huh, I would have thought it was “javascript”, haha.
Don’t take this as a push back on your preferences for objective-C, but I’m not yet convinced on these claims. It just happens to be part of the GNU compiler collection, which is fairly well optimized and very widely ported. In principal though almost any language could get the same treatment, it’s not due to any inherent advantage of objective-C as a language.
We have a tendency to stick to what we know. It’s not that C/C++ syntax’s popularly stems from it being better than everything else (C/C++ have some notorious properties), but for most of us it comes down to familiarity and a reluctance to go against the flow, so to speak. We see this with rustlang. I concede the language’s benefits while still not liking all the syntactic choices.
I predate that horrid language and wish it would have picked a different abbreviation. It has ruined being on IRC.
It’s not because it’s part of GCC (the support in GCC is … mediocre at best, actually. The support is much better in Clang!), but because it is a strict superset of C. And that means in the end it has to be native code, not code running in a VM. Most languages offering similar features for dynamic dispatch use a VM – think Java. C++’s virtual is only a fraction of what you get in terms of dynamic dispatch with Objective-C. This gives it the unique ability of having code that you can usually only have in a VM, but being able to drop down to assembly, all in the same source file. Most languages either are highlevel and have a VM and everything to allow dynamic dispatch – or they are lowlevel and go the C++ route where they just provide something like virtual and nothing else. I’d be happy to hear about another language having the same property :).
js,
Haha.
I confess that I’m too tired/lazy to find objective-c examples of what you are talking about right now. But I appreciate that there are improvements that can be had over C++. I’m actually not a big fan of C++ inheritance. I prefer when languages support explicit interfaces like java and C#. I get even more frustrated over C/C++’s reliance on include files and forward declarations – it makes these language so much more tedious than they needed to be.
I’m not clear what you mean by the VM comment. Does Objective C have managed memory? I’ve seen many language implementations with inline assembly though. I actually started learning & using assembly embedded inside pascal functions. It was handy at the time to implement low level graphics and bios routines. I use virtually no assembly these days though since most cpu functionality can be done using compiler intrinsics (*).
* I did encounter exceptions to this when I was writing an arbitrary precision math library. Despite wanting to target pure C code for portability. I was unable to get GCC to optimize output as much as I could do by hand in assembly. C didn’t expose things like carry flags and 128bit divided by 64bit.
Although I’m still unclear on your point, I agree that VM based languages are typically not good for low level work because they’re usually designed to enforce memory safety with garbage collection.
One thing that you cannot do in C++ is call a function if you don’t know what type of object you have. Let’s just say you want each class you have to have method that allows you to print a debug description. In C++, you can only do this if you have a base class with a virtual description() method and then all classes need to derive from this base class. This is because you need to have an entry in the vtable.
In Objective-C, it is more like Java (Java copied its object model from Objective-C, so not surprising). You can just say “call the method called description on the object, I don’t care which class it is”. And as long as the name is called description it will work.
Now guess where this is coming from :). Objective-C has something called protocols, which is just “a bundle of method names”. Java copied this from Objective-C almost verbatim and called it interface.
That, unfortunately, is something you don’t get rid of with ObjC, either: It explicitly splits a class in what it calls an interface (declares all methods) and and implementation.
Most (all other?) languages that allow for a dynamic dispatch with no restrictions like Objective-C usually do this with a complex VM and runtime. In ObjC, you have an extremely minimalistic runtime that is only responsible for registering classes and dispatching messages to objects. There is no garbage collector, you either manually manage your memory using reference counting, or use an extension called “Automatic Reference Counting” where the compiler inserts the calls to retain and release for you.
Yes, every lowlevel language has this. What is unique about Objective-C is that it is both, highlevel and lowlevel at the same time. Good luck having some inline assembly in your Java, for example ;).
This should work reasonably well using __int128 these days. Granted, that is a language extension, but one supported by all relevant compilers. Caution: Do not use an __int128 as part of any API!
js,
I actually prefer languages with static typing myself. But yeah if you want to call a function by name regardless of the object, C/C++ don’t provide syntactic sugar for this.
Naturally older languages tend to have more firsts,
Pascal might have done it first, although all these languages predate my introduction to programming and I’m not sure. From my perspective it’s less important who did it first and more important which languages do it well.
I don’t fault early pioneers for designs they came up with without the benefit of hindsight that we have today. But if we could send time travelers back there’s a lot of improvements that could have been made to the foundations of programming, software, internet, etc.
To me it’s not a forgone conclusion that low level languages need to support assembly. Even when inline assembly is supported, it isn’t nearly as useful/important as it used to be. Even if I need assembly I tend to prefer dedicated assemblers like NASM/FASM over quirky inline assembly. This is just my own preference though.
I haven’t tested it in years. __int128 did exist in GCC and it worked, but it would not compile down to optimal x86 assembly. Rather than use a 64bit div opcode to do 128/64=64 division (which is useful for arbitrary precision math), it basically emulated a 128/128=128, which was then cast to 64bit. The result was far worse than calling the opcode directly in assembly. It would be interesting to see if GCC can better optimize this today.