Created
February 2, 2016 01:06
-
-
Save alonecuzzo/60020aeaf63c1a2878af to your computer and use it in GitHub Desktop.
THuNKing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: 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