3. Some Cool Stuff
● Type Inference
● Explicit Mutability
● Optionals
● Named Parameters
● Enumerations
● Exhaustive Switch
● Closures
● Generics
4. Type Inference
You can do this:
var x : Int = 0
var y : String = “foobar”
var z : Bool = true
Or, you can just do this:
var x = 0
var y = “foobar”
var z = true
9. Optionals
Optionals handle the absence of a value.
Either:
1. there is some value, and it equals x
var foo : Int? = 41 // { Some 41 }
1. or, there is no value at all
var bar : Int? // nil
11. Optionals: Unwrapping
You can unwrap the value contained in the
optional by using the bang operator, like so:
var foo : Int? = 41
foo! == 41 // true
But if it’s nil, you will get a runtime error,
so don’t do that.
12. Optional Binding
var possibleNumber = "2"
if let actualNumber =
possibleNumber.toInt() {
println("(possibleNumber) has an integer
value of (actualNumber)")
} else {
println("(possibleNumber) could not be
converted to an integer")
}
13. Optional Chaining
class Person {
var name : String
var address : Address?
init(name:String, atAddress address:Address?=nil) {
self.name = name
self.address = address
}
}
class Address {
func sendLetter() {
println("Sent a letter!")
}
}
let ara = Person(name: "Ara")
let paul = Person(name: "Paul", atAddress:Address())
let people = [ara, paul]
for person in people {
person.address?.sendLetter()
}
16. Exhaustive Switch
In Swift, the compiler enforces that a switch statement contains a case
for every possible value for that type.
enum Status {
case OnTime, Delayed(Int, String)
}
let trainStatus = Status.Delayed(5, “banana on tracks”)
switch trainStatus {
case .OnTime:
println(“Train is on time!”)
case .Delayed(let minutes, let reason):
println(“Train delay: (minutes) minute(s), Reason: (reason)”)
17. Closures
Just like blocks in ObjC...but there’s a lot of optional syntax.
let names = ["Paul", "Ara", "Eric", "Tom", "Dan"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
1. sort(names, backwards)
2. sort(names, { (s1: String, s2: String) -> Bool in return s1 > s2
})
3. sort(names, { s1, s2 in return s1 > s2 } )
4. sort(names, { s1, s2 in s1 > s2 } )
5. sort(names, { $0 > $1 } )
6. sort(names, >)
“Swift is a type safe language. A type safe language encourages you to be clear about the types of values your code can work with. If part of your code expects a String, you can’t pass it an Int by mistake.
Because Swift is type safe, it performs type checks when compiling your code and flags any mismatched types as errors. This enables you to catch and fix errors as early as possible in the development process.”
But it also has a feature called Type Inference which means if the compiler can infer the type of a variable from the context of its declaration, you don’t need to explicitly write the type, it will be inferred.
Type inference means, that you even if you don’t provide a type annotation, but the var is still strongly typed -- so you can’t clobber it with a different type.
Swift provides two collection types: arrays and dictionaries, for storing collections of values.
Collections are strongly typed, so you can’t insert the wrong value into a collection, and you always know what you’re going to get when you retrieve a value.
As with other types, the type can be inferred
For collections:
an array = can’t change the size, but can’t replace a value at an index
dictionary = can’t change values
Values of most types can never be nil.
Every value must be initialized before it is used.
So how do you deal with the possibility of the absence of a value?
Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just classes.”
“Optionals are an example of the fact that Swift is a type safe language. Swift helps you to be clear about the types of values your code can work with.”
Use optionals to safely work with possibly missing values:
missing values are nil
present values are wrapped in an optional
“Swift also introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just classes.”
“Optionals are an example of the fact that Swift is a type safe language. Swift helps you to be clear about the types of values your code can work with.”
“Swift’s nil is not the same as nil in Objective-C. In Objective-C, nil is a pointer to a non-existent object. In Swift, nil is not a pointer—it is the absence of a value of a certain type. Optionals of any type can be set to nil, not just object types.”
Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just classes.”
“Optionals are an example of the fact that Swift is a type safe language. Swift helps you to be clear about the types of values your code can work with.”
Use optionals to safely work with possibly missing values:
missing values are nil
present values are wrapped in an optional
var possibleNumber = "2"
if let actualNumber = possibleNumber.toInt() {
println("(possibleNumber) has an integer value of (actualNumber)")
} else {
println("(possibleNumber) could not be converted to an integer")
}
Say we have a person -- and people in our domain always have names, but they may not have addresses. So we have the name type as a String, but the address type is an optional Address class. We have this instance method (function) on Address called sendLetter, and we want to send a letter to each person who has an address.
DEMO
so, if the optional is nil it just swallows the method call. No undefined method for nilclass error.
One of the nice things, I think, about Objective C its verbosity. I like the self-documenting nature of named parameters. Swift is a lot more flexible in that it lets you use named parameters or get rid of them all together, or even use different external param names for callers than the names used within the function definition.
Enumerations define a type for a group of related values and you can work with those values in a type-safe way. Some cool things about enumerations in Swift, is 1) they don’t need member values, unlike in C, North, South, East, West don’t equal 1, 2, 3, or 4 or whatever.
Another cool thing is an enumeration can have associated values. So, if you have a Status enum with a status of OnTime and of Delayed -- the Delayed status can have an associated delay of minutes and maybe a string that contains the reason for the delay.
Swift has a really powerful switch statement. It is exhaustive, which means the compiler forces you to check for every possible value for the type that you are checking. Now, if you are switching on integers you don’t have to have a line for ‘n’ to infinity -- you can use the default case.
Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. One of the coolest things about closures is that closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables, hence the name “closures”. Ruby has closures in the form of lambdas and procs, so I don’t really need to say much about them in Swift, other than to show the expression syntax for them in Swift.
struct Stack<T> {
var items = T[]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var stack = Stack<String>()