Extending the Swift language is cool, but be aware of what you are using

Features like the @auto_closure keyword in Swift offer a great opportunity to extend the language in ways that might not be possible in other languages. For example, in this article we used it to implement the Ruby ||= operator.

Swift doesn’t yet have a native implementation of unless or until. These are just versions of if or while, but for when the predicate is not true. Obviously you could just stick a ! in front of your if clause, but some programmers prefer the readability of the opposing versions. The implementation of ||= could be rewritten as:

@assignment func ||=<T>(inout lhs: T?, rhs: @auto_closure () -> T) {
    unless(lhs) {
        lhs = rhs()
    }
}

I know, you think, I can implement unless and until myself! What’s nice is you can make them look almost like the native flow control statements, because closure expressions can be outside the parentheses of function calls if they are the last argument.1 Implementing unless seems pretty straightforward:

func unless<L: LogicValue>(pred: L, block: ()->()) {
    if !pred {
        block()
    }
}

// doSomething only if condition is false
unless(condition) {
      doSomething()
}

until is a little trickier, because you need to execute the predicate multiple times as you loop. But @auto_closure can help you out.

func until<L: LogicValue>(pred: @auto_closure ()->L, block: ()->()) {
    while !pred() {
        block()
    }
}

// doSomething until condition becomes true
until(condition) {
    doSomething()
}

Now, the conditional expression passed as the first parameter to until will be automatically wrapped up into a closure expression and can be called each time around the loop. Any variable used in both the parentheses and the block will be captured by both, so altering it in the block will affect the result of the condition (hence the condition can become true over time).

Armed with your new unless and until functions, you write a function to search a collection for the index to the first occurrence that doesn’t match a predicate:2

func findIfNot
  <C: Collection, L: LogicValue>
  (col: C, pred: (C.GeneratorType.Element) -> L)
  -> C.IndexType? {

    var idx = col.startIndex
    until(idx == col.endIndex) {
        unless(pred(col[idx])) { return idx }
        idx = idx.succ()
    }
    return nil
}

let a = [1, 2, 3]
let isOdd = { $0%2 == 1}
// find the first non-odd number
let idx = findIfNot(a, isOdd)

Arguments about SESE and other stylistic preferences aside, this function should do the job. Except instead it generates a compiler error, 'C.IndexType' is not convertible to '()'.

Why? Because the return after the unless is a return from that closure expression between the braces, not a return from the findIfNot function. That unless closure expects no value to be returned, so when you return idx it’s an error. But if you were just blithely using this unless function you found in a library as if it were just like an if statement, you might not realize this and the compiler error may come as a shock.

Now say you instead implemented findIfNot to take in an index into the collection as an inout, and advanced that index to the first non-match, instead of returning a value (and returning the endIndex if every item matches). This is pretty bad code, but here it is:

func findIfNot
  <C: Collection, L: LogicValue>
  (col: C, inout idx: C.IndexType,
  pred: (C.GeneratorType.Element) -> L) {

    until(idx == col.endIndex) {
        unless(pred(col[idx])) { return }
        idx = idx.succ()
    }
}

let a = [1, 2, 3]
let isOdd = { $0%2 == 1}
var idx = a.startIndex 
findIfNot(a, &idx, isOdd)
// idx will not be what you would hope 

Now, no compiler error. Instead, this code will fail much more subtly, always returning as if no non-match was found. If we replace the unless with an if, the code will run forever because the until block will return before moving idx forward, and then loop again.

Unit tests should catch this of course. But as a user of built-in-like functions, you should always be aware they aren’t quite the part of the language they might seem. The bugs resulting might not be as obvious as in this case. Also, this is a good argument for using a more “functional“ approach, by writing general algorithms like findIfNot rarely and testing them thoroughly, and then reusing them as much as possible, rather than writing explicit loops.

Should Apple extend Swift to cover this kind of case? Maybe a keyword that causes a closure that doesn’t return a value to be able to pass the return statement out and act on the calling function?3 Until they do, this is definitely a gotcha to be aware of.


  1. Sadly your implementions will always be lacking one feature that if or while have – leaving off the brackets around the predicate. You can’t write unless so it can be used as if pred { } – unless Apple extends “if the last parameter is a closure expression you can have it outside the parens” to be “if there are two parameters and the last is a closure expression, you can leave the parens off the first parameter”. 
  2. If you don’t follow what the code here is doing, try reading this introduction to algorithms on collections in Swift. 
  3. If I’ve missed something huge here and there’s already a way around this issue, leave a comment! 

Implementing Ruby’s ||= operator in Swift using @autoclosure

edit: this has been updated for Swift as of Xcode 6.1 (Swift 1.1)

A common idiom in Ruby is to assign a value to a variable only if that variable isn’t already set, using the ||= operator:

s ||= "default value"

Swift doesn’t provide such an operator out of the box, but using some of the features of the language, it’s possible to implement one.

Simple first implementation

First let’s try implementing it just for string types. We need to define the operator itself first:

infix operator ||= {
    associativity right
    precedence 90
    assignment
}

And then implement it with a function:

func ||=(inout lhs: String?, rhs: String) {
    if(lhs == nil) {
        lhs = rhs
    }
}

Note the use of the assignment attribute on the operator definition, and the inout parameter on the left-hand side, which is the variable being assigned to.

This works. If you try the following

var s: String?
s ||= "first assignment"
s ||= "second assignment" 

the second assignment will have no effect on s – it will keep the value “first assignment”.

Using generics to apply to any type

What about implementing this with generics, so it will work not just for String but for any type? That’s pretty simple:

func ||=<T>(inout lhs: T?, rhs: T) {
    if(lhs == nil) {
        lhs = rhs
    }
}

Now you can use our ||= on any type optional type – String?, Int?, or any user-defined class.

Using autoclosure to avoid unncessary evaluation

Our ||= still doesn’t quite match the Ruby version. If the value on the left-hand side is already set, the statement on the right-hand side is never executed. This is important if, for example, the right-hand side were a function with other side-effects, or an expensive computation.

But by default in Swift, any statement passed to a parameter is fully executed first. To replicate the Ruby functionality, we have to use an attribute in Swift called autoclosure. This is used like this:

func ||=<T>(inout lhs: T?, rhs: @autoclosure () -> T) {
    if(lhs == nil) {
        lhs = rhs()
    }
}

What autoclosure does is wrap the arguments suppled in a closure, for later execution. Then, if they aren’t needed, they are never executed. If they are needed (in this case, because lhs is nil), the closure can be called (note the new type for rhs, and the parenthesis after rhs, indicating it is now calling a function).

To check this works, try the following, which should only print “I’ve been run” once to the console:

func printlnWhenRun() -> Int {
    println("I've been run")
    return 0
}
var i: Int?
i ||= printlnWhenRun()
i ||= printlnWhenRun()

Implementing for Boolean values

This works great for optional types, but what about the more conventional behaviour, a compound logical-OR-and-assign operator for boolean values?

Despite listing it in the Expressions precedence section of the language reference, this doesn’t appear to be implemented in Swift natively.

edit: it’s now been removed from the precedence section. You can still declare it as below though.

No problem though, we can just implement it ourselves. Here it is:

func ||=<T: BooleanType>(inout lhs: T, rhs: @autoclosure () -> T) {
    if(!lhs) {
        lhs = rhs()
    }
}

Note the BooleanType type constraint after the type parameter. This is necessary because we need to guarantee that you can pass whatever type is used into the if statement. This wasn’t necessary with the other version because it was the optional qualifier supplying this ability.1

But doesn’t this clash with the other definition? Nope. A combination of the type constraint on the logical version, and the presence of the optional parameter on the optional-assignment version, means the possible uses of these two functions are entirely disjoint, and the Swift compiler will pick the right one for you. Even a Bool? type will go to the optional-assignment version.2

Using lazy properties instead of ||=

Having done all of this, you could argue ||= isn’t all that useful in Swift because of different feature, lazy properties. These are properties of a class or struct that are only initialized for the first time when they are used – in much the same way as Ruby devs use ||=. Below is some code showing this in action:

class MyClass {
    lazy var complexThing = CreateComplexThing()
}
var c = MyClass()
// ... maybe some time later
var thing = c.complexThing  // CreateComplexThing() runs now

Obviously this only applies when your property is part of a class, not when you’re declaring a variable in a function, so maybe there’s still a place for ||=. But if not, at least we learned something implementing it.


  1. And there’s no need to constrain to objects with the ability to assign to each other – they all have that ability. There’s no “Assignable” protocol. Be nice if there were – that would imply you could overload “=”. But this ain’t C++. 
  2. It is possible to write two generic functions that overlap in their inputs, in which case you will get an “use of unresolved identifier” error from the compiler when you call the function (note, not when you define the overlapping function, which is a break from other features of generics when you get a compiler error at the time of definition rather than use). 

Mining “Effective C++” for ideas on Swift

Effective C++ by Scott Meyers is an amazingly good book. For me, it is to programming books like Watchmen is to comics – everything else I read, I feel disappointed that it isn’t as good. If you program C++ and you haven’t read it yet, get on it!

There are also several articles in the book that apply to any language – Item 28: Avoid returning “handles” to object internals, Item 32: Make sure public inheritance models “is-a.”, Item 53: Pay attention to compiler warnings. Even if you aren’t ever planning to write C++, maybe grab a friend’s copy and give it a skim.

There is a fair amount of material in there that is also applicable to Swift. Many features of modern C++ programming have fed into Swift – which isn’t surprising given Swift was born out of the LLVM team, and LLVM is written in C++. Here are a few items from the book, and how they might also apply to Swift.

edit: for the completists amongst you, this article gives a full rundown of every item in Effective C++ and how it relates to Swift. Note that many of the items are warnings on the dangers of C++, and for the most part these are all avoided in Swift.

Item 1: View C++ as a federation of languages.

Well, federation is a kinder word than hodgepodge. While Swift has been written from the ground up, so is a lot cleaner, it’s still similar to C++ in that it blends several styles (OO, generic, functional) together in one language, and you should be aware that different styles follow different conventions.

Items 3: Use const whenver possible

A welcome feature of Swift is the explicit distinction between let (const) and var (non-const) variable declarations. Using let by default, and var only when needed, is probably a good policy.

Swift also has the mutating modifier that acts like the opposite of C++’s const member function qualifier (i.e. you must specify it if you want to be able to alter internal state, rather than if you are promising not to):

struct MyStruct {
    var val = 0
    mutating func touch() -> Int { return ++val }
    func look() -> Int { return val }
}

let s = MyStruct()  // s is a constant 
s.look()    // fine - read-only
s.touch()   // compiler error

Sadly, that breaks down with classes, which don’t get to use the mutable keyword, so this compiles just fine:

class MyClass {
    var val: Int = 0
    func touch() -> Int { return ++val }
}

struct MyStructWithClassProperty {
    var val = MyClass()
}

let s = MyStructWithClassProperty()
s.val.touch()

This rules out using this feature to implement const-correct behaviour for more complex types (user-defined container classes, for example). Maybe someday it’ll be extended to cover more cases.

Item 5: Know what functions C++ silently writes and calls

Swift, like C++, silently writes some class functions for you. For example, if you don’t write an init() function for a struct or base class, but you do give all its properties default values, it will write a default initializer for you that takes no parameters. But if you do write another initializer, that takes parameters, you have to write a default one as well.

Item 12: Copy all parts of an object

Beware the seductive struct. It’s a value type, they say. It gets copied when you assign it, they say.

Well, to a point. As we saw in item 3, when you include a class as a property of a struct you leave some of those struct guarantees behind, and copying is one of them. If you were to make two copies of MyStructWithClassProperty above, they will both end up pointing at the same instance of MyClass.

Unfortunately, unlike in C++, Swift structs don’t get to implement a copy constructor. When a copy is made, it’s a shallow bitwise copy and the author of the struct has no programmable hooks to find out it’s happening. Instead you have to implement a .copy() method of your own and hope users call it.1 Maybe someday struct copy constructors will be added as a feature.

Item 13: Use objects to manage resources

Classes in Swift can implement a deinit method, that executes when the class is destroyed after all references to it are deleted. And with ARC, when that happens is a lot more deterministic than it is in Java and garbage collection. Maybe you can get some of that sweet RAII action C++ programmers are so keen on.2 The Apple docs even encourage you to do this, with an example about putting gold coins back in a bank.

But be careful! Try typing the following into a playground:

class Person {
    init() {
        println("Object is being initialized")
    }
    deinit {
        println("Object is being deinitialized")
    }
}


func deinit_demo() {
    var reference1 = Person(name: "John Appleseed")
}
deinit_demo()

and watch as you see no deinitialization logged to the console. This is presumably because the playground grabs references to everything to keep them around for playground-purposes. Fair enough, don’t use this pattern in the playground then. But you also need to watch out for the variables being captured by any closures,3 which will keep them around just by touching them, not even needing to assign them to another variable. Remember this if you’re ever trying to debug some mystifyingly resource-leaking code.

“But what about structs?”, you ask. They’re created on the stack, surely they get destroyed as soon as they fall out of scope. Well, sure, except first they can’t have a deinit method (again, maybe someday), and second, they can still be captured, so that’s no help.4

And finally, from More Effective C++:

Item 7: Never overload &&, ||, or ,

Or, in Swift’s case, totally go ahead and overload them, but make sure you do it right.

In C++, overloading || is dangerous because of the short-circuiting feature programmers are used to. Suppose you write the following:

if(cheapOp() || superExpensiveOp()) {
  doSomething()
}

Say cheapOp() returns true. That means the whole if statement can never not be true, no matter what superExpensiveOp() returns. So what’s the point of executing it? None, so in C, C++, Swift and most other languages with a ||, it won’t even get executed. If cheapOp() is true most of the time, that could give you a big performance benefit.

Except in C++, when you implement your own || operator, it’s just a regular old function, and all its parameters are fully evaluated before they are passed

The same would happen in Swift – but Swift has a feature, @auto_closure, that can be used to avoid that problem. Putting @auto_closure before a parameter means that statement gets wrapped in a closure for later execution.

So this:

if(cheapOp() || superExpensiveOp()) {
  doSomething()
}

gets rewritten as this:

if(cheapOp() || { return superExpensiveOp() }) {
  doSomething()
}

and in your implementation of the || operator you do the following

func ||(lhs: LogicValue, rhs: @auto_closure () -> LogicValue) -> Bool {
  // only if the left-hand side is false...
  if(!lhs) {
    // ...do you then need to execute the closure that wraps the second half
    if(!rhs()) {
      return false
    }
  }
  return true
}

A lot of people are excited about @auto_closure, as it enables some interesting possibilities – for example, a conditional logger that only executes expensive to-string operations if the log-level is debug, or an implementation of the ruby ||= assignment-if-nil idiom (read this article for more on that one). One of the reasons I’m excited about Swift is there are probably more of these to come as the language continues to evolve through it’s beta period.


  1. You could always talk about this issue as if it’s a deliberate feature of your collection class, like Apple does in the documentation for Swift Arrays. 
  2. Course, RAII isn’t nearly as useful when there are no exceptions waiting to pounce and pull the rug from under you at any moment, but still. 
  3. And obviously getting explicitly assigned to another variable, or being passed out of the function, but I assume you realize that. 
  4. When they are presumably whisked off to heap-land to live with the other reference-counted animals. Is Swift performing some secret autoboxing for this under the hood?