WWDC 2014
for (key, _) in dictionary {
println(key)
}
protocol Pullable {
func pull()
}
class Boards: Thing, Pullable {
func pull () {
// ...
}
}
- Use a protocol value with a conditional cast
as Pullable
- LogicValue, Printable, Sequence, IntegerLiteralConvertible, FloatLiteralConvertible, StringLiteralConvertible, ArrayLiteralConvertible, DictionaryLiteralConvertible
protocol Printable {
var description: String { get }
}
// operator declaration
operator infix ~ {}
func ~ (decorator: (Thing) -> String, object: Thing) -> String {
return decorator(object)
}
fun an(object: Thing) -> String {
return object.nameWithArticle
}
println("You want \(an ~ object).")
extension Place {
subscript (direction: Direction) -> Place? {
get {
return exits[direction]
}
set(destination: Place?) {
exits[direction] = destination
}
}
}
Any
is the empty Protocol type- but protocol types throws away type information
- great for dynamic polymorphism
- Generics conserve type information
- great for type safety
- no unsafe downcasts
- great for performance
- compiler can generate better code
- great for type safety
- but protocol types throws away type information
- Anything in Swift can be printed
func peek<T>(interestingValue: T) -> T {
//...
}
func swap<T>(inout x: T, inout y: T) {
let tmp = x
x = y
y = tmp
}
func indexOf<T: Equatable>(sought: T, inArray array: T[]) -> Int? {
for i in 0..array.count {
if array[i] == sought {
return i
}
}
return nil
}
protocol Equatable {
func == (lhs: Self, rhs: Self) -> bool
}
func != <T: Equatable>(lhs: Self, rhs: Self) -> bool {
return !(lhs == rhs)
}
- Protocols preserve type information
- Some languages throw away type information in generics
- operator requirements can be specified outside the type body
func fib(n: Int) -> Double {
return n < 2 ? Double(n) : fib(n-1) + fib(n-2)
}
let phi = fib(45)/fib(44) // 11 seconds
var fibMemo = Dictionary<Int, Double>()
func fib(n: Int) -> Double {
if let result = fibMemo[n] {
return result
}
let result = n < 2 ? Double(n) : fib(n-1) + fib(n-2)
fibMemo[n] = result
return result
}
let phi = fib(45)/fib(44) // 0.1 seconds = 100x faster
let fib: (int) -> Double = memoize {
fib, n in
n > 2 ? Double(n) : fib(n-1) + fib(n-2)
}
let fib = memoize {
fib, n in
n > 2 ? Double(n) : fib(n-1) + fib(n-2)
}
func memoize<T: Hashable, U>( body: (T)->U ) -> (T) -> U {
var memo = Dictionary<T, U>()
return { x in
if let q = memo[x] { return q}
let r = body(x)
memo[x] = r
return r
}
}
let factorial = memoize { x in x == 0 ? 1 : x * factorial(x-1) } // doesn't work
- doesn't work for recursive functions
func memoize<T: Hashable, U>( body: ((T)->U, T)->U ) -> (T) -> U {
var memo = Dictionary<T, U>()
var result: ((T)->U)! // implicitly unwrapped optional
result = { x in
if let q = memo[x] { return q}
let r = body(result, x)
memo[x] = r
return r
}
return result
}
let factorial = memoize { factorial, x in x == 0 ? 1 : x * factorial(x-1) }
- Type deduction for concision
- Trailing closure syntax for expressivity
- Truly generic functions for safety and performance
struct Stack<T> {
mutating fun push(x: T) {
items += x
}
mutating func pop() -> T {
return items.removeLast()
}
var items: T[]
}
var intStack = Stack<Int>()
for x in xs {
}
// becomes
var __g = someSequence.generate()
while let x = __g.next() {
...
}
protocol Generator {
type alias Element // An "associated type" requirement
mutating fun next() -> Element?
}
struct StackGenerator<T> : Generator {
typealias Element == T
mutating func next() -> T? {
if items.isEmpty { return nil }
let ret = items[0]
items = items[1..items.count]
return ret
}
var items: Sliece<T>
}
extension Stack : Sequence {
func generate() -> StackGenerator<T> {
return StackGenerator( items[0..itemCount] )
}
}
- Statically compiled
- Small runtime
- Transparent interaction with C and Objc-C, can deploy to previous versions of iOS and OSX
- You control the code that runs
- Comprehensible compilation with inspectable results
- No non-deterministic JITs or garbage collection pauses
- Native code instantly ready to run
- No artificial abstraction barriers
- abstraction disappears immediately during compilation
- Predictable model enables bare-to-the-metal programming
- Swift
- Parsing
- High-Level Optimization
- LLVM
- low-level optimization
- code generation
- Global analysis of your app
- No runtime penalty for using structs
- Even int and Float are structs
- Swift can run generic code directly
- Optimizer can produce specialized versions of generic code at will
- separate compilation of generics
- faster compiles
- flexibility to trade code size for speed
- Resolving dynamic method calls at compile-time
- If Swift can see where you constructed the object
- If Swift knows that a class doesn't have any subclasses
- If you've marked a method with the
@final
attribute