When learning a new language (be it a natural or programming language) one of the big first stumbling stones is getting a grasp of the basic grammar rules. For languages with a very simple and regular grammar this is less of a deal. But for others, such as German, it can be quite intimidating.

For a natural language there are basically three ways of encoding information: A language could encode information by the use of:

Patterns: An elaborate and rigid set of grammatical rules, allowing for an over all smaller set of irregular (and mostly unique) word inflections. Specialization: An exhaustively large set of irregular (and mostly unique) word inflection patterns, making up for the lack of a more complex and rigid grammar. Verbosity: An extensive set of function words making up for the lack of possibly both, a more expressive grammar, as well as inflection, at the cost of increased redundancy in the language.

What a languages lacks in one department, it usually makes up in another. A common consensus among linguists is that all languages are equally complex. (Another take is that current linguistics simply lacks a coherent theory of complexity and by that a useful, objective measure of the latter.)

Things are similar for programming languages, with the spectrum probably laying somewhere between Haskell (for its highly expressive type-system), Perl (for its infamous over-use of sigils) and AppleScript (function words everywhere).

Swift probably finds itself somewhere in the middle, leaning somewhat in the direction of Haskell.

In the context of programming one usually talks about practical expressive power when comparing languages.

Comparing an implementation of the Sieve of Eratosthenes in Objective-C …

… with an equivalent one in Swift …

… one cannot but notice how the new cool kid on the block — Swift — is getting away solving the same problem with much less noise and fewer leaky abstractions, than old-timey Objective-C.

If Swift had a splitFirst() function on Array , as Rust does for Slice …

… one could reduce it even further to …

… eliminating the unsafe array access.

Swift manages to provide such a boost in productivity and expressivity substantially thanks to the adaption of well-established features common to many functional programming languages such as pattern matching, higher-order functions, some kind of type-classes, algebraic data types, and last but not least a strong type-system.

Thanks to this tuples, enums and closures have become part of Swift’s most used and loved bells & whistles.

Tuples and enums form the foundation of pattern matching in Swift.

Pattern matching in Swift are generally marked by the prefix case … (Swift does not use pattern matching everywhere, like other FP languages do, so the case … is necessary to tell the Swift compiler when use it):

Like, for example, when one wanted to make use of the result of the splitFirst() function:

But wait, that’s far from idiomatic Swift, isn’t it? One would most likely write something like this instead …

… and have it lowered to the former by the Swift compiler.

Syntactic Sugar

Swift makes use of this so-called syntactic sugar to make working with it more convenient and to allow for progressive disclosure:

Swift’s if let foo = bar { } is syntactic sugar for the more verbose if case let .some(foo) = bar { } , allowing one to learn to use T? while sparing one a trip down the rabbit hole of learning what an enum is and how it works.

Interestingly up until Swift 2.x the following code actually worked, as Swift was simply pattern matching against .Some(_) :

With Swift 3.0.0 this turned into the rather misleading error:

Error: enum case ‘ Some ’ not found in type ‘ Maybe<Int> ’.

… which with Swift 3.0.1 was then changed further into the current more useful error:

Error: initializer for conditional binding must have Optional type, not ‘Maybe’.

Another example of syntactic sugaring is for element in sequence { … } , which gets lowered, or may I say desugared, to:

Or take returning an instance of T from a function (_) -> T? :

… which gets lowered to:

And things get even funkier with indirect enums:

… which gets lowered down to something like this:

… with Box<T> denoting a heap-allocated instance of T .

While at first all this doesn’t look like much of an improvement from the type declaration alone, the benefits become quite obvious when trying to actually use the type:

The sugar-free version of this would look something like this (assuming Swift could pattern match on classes):

Apart from a LISP joke hiding in plain sight it should be uncontroversial to state that the former does much better in conveying one’s intentions.

Syntactic sugar makes complicated things look simple.

Syntactic Salt

While syntactic sugar aims to make it easier to write good code, syntactic salt aims to make it harder to write bad code.

As such Swift requires one to add a break -statement to an empty switch -block, even though those break by default in Swift.

Or take the requirement to append override … to a function declaration if one intends to override it.

The compiler has all the information it needs to figure these things out on its own. But as both things were cause of many bugs in languages that came before Swift, its authors decided to make things more explicit.

Syntactic Saccharin

Syntactic saccharin refers to syntactic sugar that, while having good intentions, fails to do its thing, possibly making things even worse than without it.

One pattern that causes syntactic sugar to turn into syntactic saccharin is when the former, while trying to make things simpler, ends up introducing its own exceptions which now need to be learned in addition to the things it tries to simplify.

Assigning a non-optional value to an optional one works for both its de-sugared form = .some(42) , as well as its sugared one: = 42 :

This is great for progressive disclosure, as it allows new users to get up to speed with Swift rather quickly.

The downside of syntactic sugar is that it can give users a wrong image of a language’s semantics and in the worst case a false sense of safety.

As such a new user of Swift might deduce that any occurrence of type T? can always be filled with values of type T , as that’s what’s what clearly appears to be happening in the snippet above.

Reading through the official book on Swift one would further come across this:

You can put parentheses around a named type or a compound type. However, adding parentheses around a type doesn’t have any effect. For example, (Int) is equivalent to Int .

So, one would come to the conclusion, that the above could also be expressed like this (and indeed, it can):

So, if this works with a single element, one might reason, then doing it with two shouldn’t be too far off, or should it?

Error: cannot express tuple conversion ‘ (Int, Int) ’ to ‘ (Int?, Int?) ’.