I hate Swift.
I know this isn’t the sort of thing that, as a developer of macOS and iOS software I’m supposed to say. After all, Swift is new, Swift is great, Swift has idioms which prevent you from getting into trouble. And all things New And Improved!™ are supposed to be better.
Worse, if you’re a neanderthal like me who hates Swift, it’s because you’re a Bad Person. Bad people are terrible software developers, people who don’t know what they’re doing, people who don’t understand the way.
But I’m going to say it anyway.
I hate Swift.
Now don’t get me wrong; there are a lot of things Swift does really well. Swift handles null pointers and null references really well. I like the fact that a nullable type is a first-class object that requires explicit handling and explicit unboxing. I appreciate the ‘?’ operator for optional-chaining, and the ‘!’ operator for forced-value expression, and the ‘??’ operator for providing a default for a nullable variable. Granted all this took getting used to, but I appreciate them because they cause one to try to write better code, if used mindfully.
But Swift is a persnickety language, and it definitely has a “happy path.”
Meaning if you’re using Swift to string together some pre-existing views and controls and carry the data from those controls around to other places in your code–the 90% of the stuff you have to do in order to make a working macOS or iOS application–it’s fantastic. It’s great. The persnickety element sometimes blocks your flow and makes you think “hey, should I be doing this?” or “hey, shouldn’t I deal with this potential problem?” But it works.
For the happy path. For the 90% of your code.
But Swift definitely intrudes. It definitely has a way in which it wants you to do things.
Now let’s be clear: I personally prefer to catch as many errors at compile time than at run time as possible. And Swift’s optional-chaining/forced-value stuff surfaces null pointer errors as compile-time errors.
But Swift… weirdly it misses a few things.
Swift doesn’t have a way to define an abstract method or an abstract function. This makes certain idioms hard to write–and worse, Swift’s answer, used in parts of Apple’s frameworks, is to make what could have been a compile-time error (undeclared abstract method, such as you see in Java or C++) into a run-time error (by creating an ’empty’ base declaration that throws an exception).
So Swift’s nannying is… incomplete. Sometimes woefully so.
And weirdly so, given how persnickety Swift can be sometimes. “Yes, you have to think through exactly if and when and how this variable may be null. But an undeclared method you needed to declare? Meh, CRASH!
And Swift’s persnickety behavior makes anything revolving around pulling apart a String and handling it as an array of Characters… challenging. It can be done, but you wind up wandering down a hierarchy of declarations (String, Substring–which, ironically enough, is not a String, Character–which looks like a string except it isn’t, weird things like UTF16View, UTF8View and arrays of things that look like integers, as well as a whole bevy of ‘Unsafe’ pointer things whose declaration and usage seems to change every five minutes with language revisions) that makes writing a per-character lexical analysis program an exercise of looking through the hierarchy of Swift declarations to figure out the current ‘one true way’ to handle strings.
(And yes, I understand that Swift’s string handling is constrained by the Unicode standard, which itself is… oddly twisted in weird ways, such as with the handling of characters in the U+10000 – U+10FFFF “supplementary planes” range a pain in the ass, especially if you think “well, just encode it as an array of 16-bit unsigned integers”, as Java does. Simply saying “well, we can ignore these” doesn’t work if you ever want to write an emoji. 😀 But can’t I just get an array of 16-bit integers or 32-bit integers, manipulate that, and turn that back into a String without making a whole Federal production out of it?)
And what the hell was Apple thinking with the “Unsafe” pointer reference types? I mean, I pride myself in understanding the ins and outs of odd corners of a programming language–but really, what the hell, man; what the hell? At least Java dealt with it by making arrays of basic types first-class citizens, instead of returning unsafe blobs of memory that may or may not be represented by some genericized unsafe reference thing that may or may not be convertible to something useful.
All of this means that as soon as you wander off the happy path: as soon as you start (for example) implementing some complex algorithm involving anything more complex than a push-down stack or want to implement some string parsing system or build something using a complex array of data structures–or God help you if you need to handle memory in a way that is off the happy path of ARC–Swift definitely gets in the way.
And writing an algorithm, like building a variation of a convex hull algorithm in Swift, becomes akin to wrestling a bear.
Which I hate, because in implementing the algorithm I’m already wrestling a bear–and I don’t need Swift to intrude every five minutes with a “you can’t express walking down a stack with a pointer” or “you want to autoincrement what?” or “no, you can’t simply delete the middle five objects and return it as new object.”
It’s not that Swift makes implemneting such an algorithm impossible. But Swift keeps wanting to poke itself into the conversation when I need it to shut the hell up for a minute so I can think about my algorithm instead!
So I hate Swift.
Honestly, I prefer using Objective C to Swift. Or heck, dropping into C or C++.
Hell, I’ll take Java over Swift if I need to do anything more complex than “glue button A to array B so table C can be populated with the sorted values.” Even though Java requires you to be incredibly verbose about everything–at least you can use the code refactoring functionality of a good Java IDE to track all those weird imports and type declarations. Though honestly I think Java could use some of Swift’s compiler mojo to eliminate some of the verboseness.
After all, do I need to write `thing = Enum.VALUE;` when the compiler already knows `thing` is of type `Enum`?
But yeah, I’d rather take verbose Java over concise and persnickety Swift for writing anything more complex than the plumbing that is 90% of modern app development.
Plumbing which, I will grant, Swift absolutely excels at.