16. var car: String? // car is nil
car = "Porsche"
!
// checked
if let actuallyACar = car {
if actuallyACar.hasPrefix("P") {
println("It's a 'P'")
}
}
!
// unchecked
// fatal error: unexpectedly found nil while
// unwrapping an Optional value
if car!.hasPrefix("P") {
println("It's a 'P'")
}
!
// chaining
if let hasPrefix = car?.hasPrefix("P") {
if hasPrefix {
println("It's a 'P'")
}
}
19. enum Optional<T> : Reflectable, NilLiteralConvertible {
case None
case Some(T)
init()
var hasValue: Bool { get }
!
static func convertFromNilLiteral() -> T?
}
20. // checked
if let actuallyACar = car {
if actuallyACar.hasPrefix("P") {
println("It's a 'P'")
}
}
// sugar free
var car: Optional<String> = "Porsche"
!
switch car {
case .None:
println("nothing here")
case .Some(let actuallyACar):
if actuallyACar.hasPrefix("P") {
println("It's a 'P'")
}
}
30. Thou shalt initialise all properties of your type!
Thou shalt not call super init before properties are initialised!
Thou shalt not call class methods until all properties are initialised!
Thou shalt not use super properties before super.init!
Thou shalt only call designated initialisers on the superclass!
Thou shalt not call super initialisers from convenience initialisers!
Thou shalt not call class methods before super.init !
Thou shalt not kill
31. Thou shalt initialise all properties of your type!
Thou shalt not call super init before properties are initialised!
Thou shalt not call class methods until all properties are initialised!
Thou shalt not use super properties before super.init!
Thou shalt only call designated initialisers on the superclass!
Thou shalt not call super initialisers from convenience initialisers!
Thou shalt not call class methods before super.init !
Thou shalt not kill
32. Thou shalt initialise all properties of your type!
Thou shalt not call super init before properties are initialised!
Thou shalt not call class methods until all properties are initialised!
Thou shalt not use super properties before super.init!
Thou shalt only call designated initialisers on the superclass!
Thou shalt not call super initialisers from convenience initialisers!
Thou shalt not call class methods before super.init !
Thou shalt not kill
33. Thou shalt initialise all properties of your type!
Thou shalt not call super init before properties are initialised!
Thou shalt not call class methods until all properties are initialised!
Thou shalt not use super properties before super.init!
Thou shalt only call designated initialisers on the superclass!
Thou shalt not call super initialisers from convenience initialisers!
Thou shalt not call class methods before super.init !
Thou shalt not kill
34. Thou shalt initialise all properties of your type!
Thou shalt not call super init before properties are initialised!
Thou shalt not call class methods until all properties are initialised!
Thou shalt not use super properties before super.init!
Thou shalt only call designated initialisers on the superclass!
Thou shalt not call super initialisers from convenience initialisers!
Thou shalt not call class methods before super.init !
Thou shalt not kill
35. Thou shalt initialise all properties of your type!
Thou shalt not call super init before properties are initialised!
Thou shalt not call class methods until all properties are initialised!
Thou shalt not use super properties before super.init!
Thou shalt only call designated initialisers on the superclass!
Thou shalt not call super initialisers from convenience initialisers!
Thou shalt not call class methods before super.init !
Thou shalt not kill
36. Thou shalt initialise all properties of your type!
Thou shalt not call super init before properties are initialised!
Thou shalt not call class methods until all properties are initialised!
Thou shalt not use super properties before super.init!
Thou shalt only call designated initialisers on the superclass!
Thou shalt not call super initialisers from convenience initialisers!
Thou shalt not call class methods before super.init !
Thou shalt not kill
37. Thou shalt initialise all properties of your type!
Thou shalt not call super init before properties are initialised!
Thou shalt not call class methods until all properties are initialised!
Thou shalt not use super properties before super.init!
Thou shalt only call designated initialisers on the superclass!
Thou shalt not call super initialisers from convenience initialisers!
Thou shalt not call class methods before super.init !
Thou shalt not kill
38. class Cat: Animal {
...
init(name: String, isLongHaired: Bool) {
// initialize *all* class properties
// no calls to 'self' methods here
super.init(name: name)
// perform initialisation that requires self & super
// possibly update superclass properties
}
convenience init() {
// can only call designated initializers on self
self.init(name: "kitty", isLongHaired: false)
}
}
55. A variable class
class Coordinate {
var x: Int = 0, y: Int = 0
}
!
var coord = Coordinate()
coord.x = 56
!
coord = Coordinate()
coord.y = 57;
Class variable, you
can change properties
and re-assign
56. A constant class (almost)
class Coordinate {
var x: Int = 0, y: Int = 0
}
!
let coord = Coordinate()
coord.x = 56
!
// fails here
coord = Coordinate()
coord.y = 57
A constant class can
be mutated
A constant class
cannot be re-assigned
57. A variable struct
struct Coordinate {
var x: Int = 0, y: Int = 0
}
!
var coord = Coordinate()
coord.x = 56
!
coord = Coordinate()
coord.y = 57
Variable struct, you
can change properties
and re-assign
Just like variable
classes!
58. Constant structs are
immutable :-)
struct Coordinate {
var x: Int = 0, y: Int = 0
}
!
let coord = Coordinate()
// error: fails here
coord.x = 56
!
coord = Coordinate()
coord.y = 57
!
Constant struct, you
cannot mutate it!
This is super-awesome,
by changing a keyword,
you change the
mutability of the entire
object.
59. Strings, Arrays and
Dictionaries are structs
// a variable array
var coord = [1,2,3,4]
!
// can be mutated!
coord[1] = 5 // “[1, 4, 3, 4]”
// a constant array
let coord = [1,2,3,4]
!
// error: ’@lvalue $T5' is not identical to 'Int'
coord[1] = 5;
60. Creating Immutable Types
struct Coordinate {
var x = 0, y = 0
func transpose() {
let temp = x
// error: cannot assign to ‘x’ in ‘self’
x = y
y = temp
}
}
61. Mutating Functions
struct Coordinate {
var x = 0, y = 0
mutating func transpose() {
let temp = x
// no error!
x = y
y = temp
}
}
62. Mutating Functions
// a variable coordinate
var coord = Coordinate()
coord.transpose()
!
!
!
// a constant coordinate
let constCoord = Coordinate()
!
// error: immutable value of type ‘Coordinate'
// only has mutating members named 'transpose'
constCoord.transpose()
63. Structs are value-types
func trimArrayToLength<T>(array: [T], length: Int) {
while array.count > length {
// error: immutable value of type '[T]' only
// has mutating members named 'removeLast'
array.removeLast()
}
}
64. Structs are value-types
func trimArrayToLength<T>(inout array: [T], length: Int) {
while array.count > length {
array.removeLast()
}
}
!
var myArray = [1,3,5,3,8,9]
trimArrayToLength(&myArray, 3)
println(myArray) // [1,3,5]
65. Whenever you start typing var,
type let instead, only changing it
back to var if it does not compile!
67. First-class functions
import Foundation
!
func square(number: Double) -> Double {
return number * number
}
!
let a = 3.0, b = 4.0
let c = sqrt(square(a) + square(b))
println(c) // 5.0
68. import Foundation
!
func square(number: Double) -> Double {
return number * number
}
!
let operation = square
!
let a = 3.0, b = 4.0
let c = sqrt(operation(a) + operation(b))
println(c) // 5.0
69. Function types
let operation = square
The type of
operation is being
inferred
But what *is* the
type?
74. // non functional
var evens = [Int]()
for i in 1...10 {
if i % 2 == 0 {
evens += [i]
}
}
!
var evenSum = 0
for i in evens {
evenSum += i
}
// functional
evenSum = Array(1...10)
the sum of all
even numbers
between 1 and 10
.filter { (number) in number % 2 == 0 }
.reduce(0) { (total, number) in total + number }
75. Partial application
func createSplitter(separator:String) -> (String -> [String]) {
func split(source:String) -> [String] {
return source.componentsSeparatedByString(separator)
}
return split
}
let data = "5,7;3,4;55,6"
let commaSplitter = createSplitter(",")
commaSplitter(data)
!
let semiColonSplitter = createSplitter(";")
semiColonSplitter(data)
79. Sorting an array
let animals = ["fish", "cat" , "chicken", "dog"]
!
func isBefore(one: String, two:String) -> Bool {
return one < two
}
!
let sortedStrings = animals.sorted(isBefore)
!
println(sortedStrings) // [cat, chicken, dog, fish]
!
!
80. Closure expressions as
anonymous functions
let sorted = animals.sorted({
(one: String, two: String) -> Bool in
return one > two
})
81. let sorted = animals.sorted({
(one: String, two: String) -> Bool in
return one > two
})
46 characters
82. let sorted = animals.sorted({
(one, two) -> Bool in
return one > two
})
32 characters
83. let sorted = animals.sorted({
(one, two) in
return one > two
})
26 characters
84. let sorted = animals.sorted({
one, two in
return one > two
})
24 characters
85. let sorted = animals.sorted({
one, two in
one > two
})
19 characters
86. 50% smaller
let sorted = animals.sorted({
(one: String, two: String) -> Bool in
return one > two
})
let sorted = animals.sorted({
one, two in
one > two
})
97. for-in and sequence
class Fibonacci: SequenceType {
func generate() -> GeneratorOf<Int> {
var current = 0, next = 1
return GeneratorOf<Int> {
var ret = current
current = next
next = next + ret
return ret
}
}
}
!
for num in Fibonacci() {
println(num) // 0, 1, 1, 2, 3, 5, 8, 13
}
!
http://www.scottlogic.com/blog/2014/06/26/swift-sequences.html
98. Literal conversion
class Person: StringLiteralConvertible {
let name: String
required init(name: String) {
self.name = name
}
class func convertFromStringLiteral(value: StringLiteralType) -> Self {
return self(name: value)
}
class func convertFromExtendedGraphemeClusterLiteral(value: String) -> Self {
return self(name: value)
}
}
!
var people: [Person] = ["Bob", "Frank", "Brian"]