The biggest news out of the recent Worldwide Developers Conference keynote a couple of weeks ago has to be Apple’s announcement of a brand new programming language called Swift. A small team worked on Swift, in secret, for four years and their efforts paid off. While Apple was successful in gradually bringing more modern language features to Objective-C, a 30-year old language, over the years, Swift represents a clean break and brings with it a new syntax and some exciting features that other languages like Ruby, Scala, and Javascript have enjoyed. Here are some that I’m most excited about:
1. Type Inference
Swift is a type safe language, so the compiler performs type checks to ensure that if a part of your code expects an Integer then you can’t pass it a String instead. Type inference is a great feature that allows you to dispense with explicit declarations of a variable’s or return value’s type. If the compiler can infer the type from the context of the declaration, then you don’t need to be explicit. So, while you could write this:
var x : Int = 0
var y : String = “foobar”
var z : Bool = true
With type inference, you can just write this:
var x = 0
var y = “foobar”
var z = true
And the compiler will infer, for example, that x should be of type Integer, since the initializing value 0 is of type Integer.
2. Explicit Mutability
In Swift, to declare a mutable variable you use the ‘var’ keyword. To declare a const, you use the ‘let’ keyword. Attempting to set a constant that has been declared with let after initializing it will lead to a compiler error.
var x = 0
x = 1
x // x == 1
let y = 0
y = 1 // COMPILER ERROR
3. Optionals
Values of most types can never be nil in Swift. Every value must be initialized before it is used. So:
var x = 0
x = nil // COMPILER ERROR
var y : String // COMPILER ERROR
But we need some way of representing the absence of a value, and for that, Swift has a great feature called optionals. An optional is a type that either has a value or has no value. They work for any type, including primitives. You declare an optional, like this:
var foo : Int? = 41 // { Some 41 }
an optional declared without an initializing value will be nil.
var bar : Int? // nil
and, an optional typed variable is the only variable that can be set to nil.
var baz : Int? = 41 // { Some 41 }
baz = nil // nil
In order to access the value inside an optional you must unwrap the optional, and Swift provides a number of ways of doing that.
First, you can explicitly unwrap an optional, like this:
var foo : Int? = 41 // { Some 41 }
foo! // 41
But be careful, as this is unsafe. If the value inside the optional is nil, and you unwrap the optional with a bang, you will get a runtime error. You should only unwrap an optional after checking if the value inside is nil, and one way of doing that is by using optional binding.
var optionalInt : Int? = nil
if let value = optionalInt {
println(“optionalInt has a value of \(value)”)
} else {
println(“optionalInt is “nil)
}
Here, we use “if let” to guard against a possible nil value.
An optional is defined as a simple enumeration, like this (I’ve left part of the definition out):
enum Optional : LogicValue, Reflectable {
case None
case Some(T)
…
…
}
where T is the value type wrapped inside the optional. This means that you can also use Swift’s fancy new switch syntax to safely unwrap the value.
var optionalInt : Int? = 2
switch optionalInt {
case .Some(let value):
println(“optionalInt has a value of \(value)”)
case .None:
println("optionalInt is nil")
}
- Optional Chaining
All of the above methods for unwrapping optionals are great, but if you have optional class instances that themselves have optional properties you’ll end up with a bunch of nested “if let”’s. The solution for that problem is optional chaining.
Say we have a Person class that has an optional Address class property. We want to send a letter to everybody, but only if they have an address of course. We can do something like this:
class Person {
var name : String
var address : Address?
init(name:String, address:Address?=nil) {
self.name = name
self.address = address
}
}
class Address {
func sendLetter() {
println("Sent a letter!")
}
}
let john = Person(name: “John”)
let jane = Person(name: “Jane”, address:Address())
let people = [john, jane]
for person in people {
person.address?.sendLetter()
}
// sends one letter to Jane
We create two people, one of whom (John) does not have an address. When person == jane, we successfully call the sendLetter function on her address. But, when person == john, even though John’s address property is nil, we don’t get a runtime error and execution continues!
That’s just a small sample of some cool new things in Swift, there’s a ton more that I’ll be writing about in the near future, so keep a look out for my next article.
Below is some of this content in slide form, from a presentation I gave on Swift at B'more on Rails.
A Few Interesting Things in Apple's Swift Programming Language from SmartLogic
Follow SmartLogic on Twitter for more posts.