Skip to content

Instantly share code, notes, and snippets.

@alonecuzzo
Created February 2, 2016 01:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alonecuzzo/60020aeaf63c1a2878af to your computer and use it in GitHub Desktop.
Save alonecuzzo/60020aeaf63c1a2878af to your computer and use it in GitHub Desktop.
THuNKing
//: Playground - noun: a place where people can play
import UIKit
// Self
protocol OwlType {
func hootWithOwlType(owl: Self)
}
class GreatHornedOwl: OwlType {
func hootWithOwlType(owl: GreatHornedOwl) {
// Great Horned Owl Hoot
print("Hoot it out!")
}
}
class BarnOwl: OwlType {
func hootWithOwlType(owl: BarnOwl) {
// Barn Owl Hoot
print("Hooting, Fool, I'm Hooting!")
}
}
extension OwlType where Self: GreatHornedOwl {
func hootWithOwlType(owl: GreatHornedOwl) {
// Great Horned Owl Hoot
print("Hoot Fool, Hoot!")
}
}
// associatedType
protocol RaptorType {
typealias PreyType
func hunt() -> [PreyType]
func eat(type: PreyType)
}
protocol Preyable {}
struct Mouse: Preyable {}
struct HummingBird: Preyable {}
struct Vole: Preyable {}
struct GrassHopper: Preyable {}
class EasternScreechOwl: RaptorType {
func hunt() -> [Mouse] {
return [Mouse]()
}
func eat(type: Mouse) {}
}
class GreyOwl: RaptorType {
func hunt() -> [HummingBird] {
return [HummingBird]()
}
func eat(type: HummingBird) {}
}
//protocols can be used:
//1. parameter or return type in a function
//2. type of a constant, value, property
//3. type of an array or other container
//but generic protocols can only be used as generic constraints!
class Forest<R: RaptorType> {}
func raptorWatch<R: RaptorType>(raptor: R) {}
//let theOwl: RaptorType //err
//Swift is an Ahead of Time compiled language. It needs to be able to infer concrete types at compile time. Associated types inside a protocol declaration are abstract. Every type that isn't a function/class needs to be concrete.
let greyOwl: GreatHornedOwl
let easternScreechOwl: EasternScreechOwl
//var someRaptor: RaptorType = random() % 2 == 0 ? greyOwl : easternScreechOwl
//let prey = someRaptor.hunt()
let food: [Preyable] = [GrassHopper(), HummingBird(), Vole(), Mouse()]
//let raptors: [RaptorType] = [greyOwl, easternScreechOwl, easternScreechOwl, greyOwl]
//
//
//for (prey, raptor) in raptors.enumerate() {
// raptor.eat(prey) // what type is prey?? can't be sure
//}
//enter type erasure
//erase abstract in favor of a more concrete type
//a thunk is something that passes
//apple uses it: https://developer.apple.com/library/ios/documentation/Swift/Reference/Swift_AnySequence_Structure/index.html#//apple_ref/swift/structctr/AnySequence/s:FVSs11AnySequencecu__Rqd__Ss13GeneratorTypezq_qqd__S0_7Element_FMGS_q__FFT_qd__GS_q__ with AnySequence
class AnyRaptorType<T>: RaptorType {
private let _hunt: Void -> [T]
private let _eat: T -> Void
required init<U: RaptorType where U.PreyType == T>(_ raptor: U) {
_hunt = raptor.hunt
_eat = raptor.eat
}
func hunt() -> [T] {
return _hunt()
}
func eat(type: T) {
return eat(type)
}
}
let concreteRaptor: AnyRaptorType<Vole>
let raptorz = [AnyRaptorType<HummingBird>]()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment