Skip to content

Instantly share code, notes, and snippets.

@elm4ward
Last active April 21, 2016 20:24
Show Gist options
  • Save elm4ward/9cfbdea339992051f51870265052f7ec to your computer and use it in GitHub Desktop.
Save elm4ward/9cfbdea339992051f51870265052f7ec to your computer and use it in GitHub Desktop.
// ----------------------------------------------------------------------------------------------------
// Protocol Flow in Swift
//
// http://elm4ward.github.io/swift/protocols/2016/04/02/protocollisions.html
//
// 1. The Protocols
// 2. The Flow
// 3. String Example
// 4. Custom Example
// ----------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------
// MARK: - 1. The Protocols
//
// Three of a kind
// ----------------------------------------------------------------------------------------------------
protocol Fetchable {
associatedtype FetchedType
static var all: [FetchedType] { get }
}
protocol Changeable {
associatedtype ChangeResultType
static var changeTo: Self -> ChangeResultType { get }
}
protocol Mergeable {
associatedtype MergeResultType
static var merge: (MergeResultType, Self) -> MergeResultType { get }
static var identity: MergeResultType { get }
}
// ----------------------------------------------------------------------------------------------------
// MARK: - 2. The One and only flow implementation
//
// Taking care of all 3 protocols
// ----------------------------------------------------------------------------------------------------
extension Fetchable where Self.FetchedType: Changeable, Self.FetchedType.ChangeResultType: Mergeable {
typealias MergeableType = Self.FetchedType.ChangeResultType
typealias ChangeableType = Self.FetchedType
static func fetchItChangeItMergeIt() -> MergeableType.MergeResultType {
return all
.map(ChangeableType.changeTo)
.reduce(MergeableType.identity, combine: MergeableType.merge)
}
}
// ----------------------------------------------------------------------------------------------------
// MARK: - 3. Example - String
// ----------------------------------------------------------------------------------------------------
extension String: Fetchable {
static let all = ["a", "b", "c"]
}
extension String: Changeable {
static let changeTo: String -> Int = { $0.characters.count }
}
extension Int: Mergeable {
static let identity = 0
static let merge: (Int, Int) -> Int = (+)
}
String.fetchItChangeItMergeIt()
// -> 3
// ----------------------------------------------------------------------------------------------------
// MARK: - 4. Example - Cusotm
//
// we can even combine the Protocols
// ----------------------------------------------------------------------------------------------------
protocol TheWholeEnchilada: Fetchable, Changeable {}
struct Data {
let name: String
}
extension Data: TheWholeEnchilada {
static let all = [Data(name: "a"), Data(name: "bb"), Data(name: "ccc")]
static let changeTo: Data -> String = { $0.name }
}
extension String: Mergeable {
static let identity = ""
static let merge: (String, String) -> String = { $0.isEmpty ? $1 : $0 + ", " + $1 }
}
Data.fetchItChangeItMergeIt()
// -> "a, bb, ccc"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment