Skip to content

Commit

Permalink
Add getters playground
Browse files Browse the repository at this point in the history
  • Loading branch information
mbrandonw committed Mar 19, 2018
1 parent 0e21b6e commit 1998e89
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@

struct User {
let id: Int
let email: String
}

let user = User(id: 1, email: "[email protected]")
user.id
user.email

let f = { (user: User) in user.id } >>> String.init

\User.id // KeyPath<User, Int>

user[keyPath: \User.id]
user.id

func get<Root, Value>(_ kp: KeyPath<Root, Value>) -> (Root) -> Value {
return { root in
root[keyPath: kp]
}
}

get(\User.id) >>> String.init


extension User {
var isStaff: Bool {
return self.email.hasSuffix("@pointfree.co")
}
}

user.isStaff

\User.isStaff
user[keyPath: \User.isStaff]

get(\User.isStaff)


let users = [
User(id: 1, email: "[email protected]"),
User(id: 2, email: "[email protected]"),
User(id: 3, email: "[email protected]"),
User(id: 4, email: "[email protected]")
]

users
.map { $0.email }

//users
// .map(\User.email)


extension Sequence {
func map<Value>(_ kp: KeyPath<Element, Value>) -> [Value] {
return self.map { $0[keyPath: kp] }
}
}

users
.map(\User.email)
users
.map(\.email)
//users
// .filter(\.isStaff)

users
.map(get(\.email))

users
.filter(get(\.isStaff))

users
.map(get(\.email))
.map(get(\.count))

users
.map(get(\.email) >>> get(\.count))


users
.map(get(\.email.count))

users
.filter(get(\.isStaff) >>> (!))


users
.filter((!) <<< get(\.isStaff))

users
.sorted(by: { $0.email.count < $1.email.count })

//users.sorted(by: <#T##(User, User) throws -> Bool#>)

func their<Root, Value>(_ f: @escaping (Root) -> Value, _ g: @escaping (Value, Value) -> Bool) -> (Root, Root) -> Bool {

return { g(f($0), f($1)) }
}


users
.sorted(by: their(get(\.email), <))

users
.sorted(by: their(get(\.email), >))

users
.sorted(by: their(get(\.email.count), >))

users
.max(by: their(get(\.email), <))?.email

users
.min(by: their(get(\.email), <))?.email

func their<Root, Value: Comparable>(_ f: @escaping (Root) -> Value) -> (Root, Root) -> Bool {

return their(f, <)
}

users
.max(by: their(get(\.email)))?.email

users
.min(by: their(get(\.email)))?.email


[1, 2, 3]
.reduce(0, +)


struct Episode {
let title: String
let viewCount: Int
}

let episodes = [
Episode(title: "Functions", viewCount: 961),
Episode(title: "Side Effects", viewCount: 841),
Episode(title: "UIKit Styling with Functions", viewCount: 1089),
Episode(title: "Algebraic Data Types", viewCount: 729),
]

episodes
.reduce(0) { $0 + $1.viewCount }

func combining<Root, Value>(
_ f: @escaping (Root) -> Value,
by g: @escaping (Value, Value) -> Value
)
-> (Value, Root)
-> Value {

return { value, root in
g(value, f(root))
}
}

episodes.reduce(0, combining(get(\.viewCount), by: +))



prefix operator ^
prefix func ^ <Root, Value>(_ kp: KeyPath<Root, Value>) -> (Root) -> Value {
return get(kp)
}

^\User.id
users.map(^\.id)

users.map(^\.email.count)
users.map(^\.email.count >>> String.init)

users.filter(^\.isStaff)
users.filter((!) <<< ^\.isStaff)

users.sorted(by: their(^\.email))
users.sorted(by: their(^\.email, >))

users.max(by: their(^\.email.count))?.email
users.min(by: their(^\.email.count))?.email

import Foundation

//NSObject().observe(<#T##keyPath: KeyPath<NSObject, Value>##KeyPath<NSObject, Value>#>, changeHandler: <#T##(NSObject, NSKeyValueObservedChange<Value>) -> Void#>)








Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
precedencegroup ForwardApplication {
associativity: left
}

infix operator |>: ForwardApplication

precedencegroup ForwardComposition {
associativity: left
higherThan: ForwardApplication
}

infix operator >>>: ForwardComposition

public func |> <A, B>(x: A, f: (A) -> B) -> B {
return f(x)
}

public func >>> <A, B, C>(f: @escaping (A) -> B, g: @escaping (B) -> C) -> (A) -> C {
return { g(f($0)) }
}

public func zurry<A>(_ f: () -> A) -> A {
return f()
}

public func flip<A, B, C>(_ f: @escaping (A) -> (B) -> C) -> (B) -> (A) -> C {

return { b in { a in f(a)(b) } }
}

public func flip<A, C>(_ f: @escaping (A) -> () -> C) -> () -> (A) -> C {

return { { a in f(a)() } }
}


precedencegroup SingleTypeComposition {
associativity: left
higherThan: ForwardApplication
}

infix operator <>: SingleTypeComposition

public func <> <A>(f: @escaping (A) -> A, g: @escaping (A) -> A) -> (A) -> A {
return f >>> g
}

public func incr(_ x: Int) -> Int {
return x + 1
}

public func square(_ x: Int) -> Int {
return x * x
}

precedencegroup BackwardsComposition {
associativity: left
}
infix operator <<<: BackwardsComposition
public func <<< <A, B, C>(_ f: @escaping (B) -> C, _ g: @escaping (A) -> B) -> (A) -> C {
return { f(g($0)) }
}

public func second<A, B, C>(_ f: @escaping (B) -> C) -> ((A, B)) -> (A, C) {
return { pair in
return (pair.0, f(pair.1))
}
}

public func map<A, B>(_ f: @escaping (A) -> B) -> ([A]) -> [B] {
return { $0.map(f) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='macos'>
<timeline fileName='timeline.xctimeline'/>
</playground>
10 changes: 10 additions & 0 deletions 0008-getters-and-key-paths/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
### [Point-Free](https://www.pointfree.co) Episode #8

### Getters and Key Paths

> Key paths aren’t just for setting. They also assist in getting values inside nested structures in a
composable way. This can be powerful, allowing us to make the Swift standard library more expressive with
no boilerplate.

This directory contains code from Point-Free Episode #8:
[Getters and Key Paths](https://www.pointfree.co/episodes/ep8-getters-and-key-paths)

0 comments on commit 1998e89

Please sign in to comment.