Rust and Swift (iii)
Operators, including overloading, and thoughts on brevity.
I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. Iâd be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. (See all parts in the series.)
I just hit operators in the Swift book. First question: are operators special syntax, or are they sugar for protocol
s? (Every modern language I use or even have played with handles them as sugar for another language constructâPython, Ruby, Io, Elixir, and Rust, to name just a few ranging over a substantial variety of ages and styles.)
Oh. I did the requisite digging, and operators are functions (which is okay) defined in the global namespace (:sigh:) Swift
module.1 I say âokayâ rather than good because the justification offered is that this is the only way to make the operators work as binary operators between existing instances of types. But that elides the fact that, if thatâs the case, it is so because of other language design decisions. This seems like a perfect place to use a protocol
, but perhaps (unlike Rustâs trait
) theyâre not sufficiently capable to handle this? Thatâs an open question; I have no idea about the answer.
Interestingly, Rust has several fewer operators than Swift, even apart from those mentioned in my previous post. It drops the pre- and post-increment operators entirely (as does Python), since their results can always be accomplished in other ways with less potential for confusion. Swift keeps them, no doubt in part because most (Objective) C programs are deeply familiar with them and with idioms associated with them.
I learned a few new things about Rustâs operators as well: the Boolean ||
and &&
operators and its bitwise |
and &
operators differ not only in that the former are short-circuit operators and the latter are not. Obviously you can also do things like bit-wise flag operations with the latter, but the reference emphasizes the short-circuiting behavior. This makes perfect sense, but it wasnât something Iâd ever considered explicitly before.
There is no ternary operator in Rust, because of how it handles the relationship between expressions and statements. Swift keeps it. Thatâs an interesting reflection of differences in design: Rust dropped it because if
blocks are expressions, so itâs redundant, and they have had a goal of removing unnecessary features. (See the discussion on dropping the ternary operatorâwith an interesting aside from Brendan Eich on JavaScriptâhere). Note that this is not a criticism of Swift, just an observation, though I do really like Rustâs expression-driven approach.
The ??
ânil coalescing operatorâ, on the other hand, I actively dislike. This seems like shorthand for the sake of shorthand, partly necessitated by the existing drive toward shorthand with optional types in Swift. Sometimes brevity can lead to decreased clarity. Eliding too much, or subsuming it into shorthand, makes the language harder to hold in your head and requires you to slow down more for parsing each line.
Nothing surprising (or different) between the standard boolean operators in the two languages.
I wonder how many times the word âconciseâ (or synonyms of it) appear in the Swift book? Itâs increasingly clear to me reading that brevity is one of the primary design goals. Maybe itâs just me, but that actually seems a little weird. Brevity is good so far as it goes, but legibility is much better.
- Previous: Basic types and the syntax around them.
- Next: Language design tradeoffs, highlighted by string manipulation.