-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e3e6387
commit 1632b5d
Showing
6 changed files
with
1,321 additions
and
3 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ A library for function composition. | |
- [`prop`](#prop) | ||
- [`over` and `set`](#over-and-set) | ||
- [`mprop`, `mver`, and `mut`](#mprop-mver-and-mut) | ||
- [`zip`](#zip) | ||
- [FAQ](#faq) | ||
- [Installation](#installation) | ||
- [🎶 Prelude](#-prelude) | ||
|
@@ -309,6 +310,79 @@ let request = with(URLRequest(url: url), concat( | |
)) | ||
``` | ||
|
||
### `zip` and `zip(with:)` | ||
|
||
This is a function that Swift ships with! Unfortunately, it's limited to pairs of sequences. Overture defines `zip` to work with up to ten sequences at once, which makes combining several sets of related data a snap. | ||
|
||
```swift | ||
let ids = [1, 2, 3] | ||
let emails = ["[email protected]", "[email protected]", "[email protected]"] | ||
let names = ["Blob", "Blob Junior", "Blob Senior"] | ||
|
||
zip(ids, emails, names) | ||
// [ | ||
// (1, "[email protected]", "Blob"), | ||
// (2, "[email protected]", "Blob Junior"), | ||
// (3, "[email protected]", "Blob Senior") | ||
// ] | ||
``` | ||
|
||
It's common to immediately `map` on zipped values. | ||
|
||
``` swift | ||
struct User { | ||
let id: Int | ||
let email: String | ||
let name: String | ||
} | ||
|
||
zip(ids, emails, names).map(User.init) | ||
// [ | ||
// User(id: 1, email: "[email protected]", name: "Blob"), | ||
// User(id: 2, email: "[email protected]", name: "Blob Junior"), | ||
// User(id: 3, email: "[email protected]", name: "Blob Senior") | ||
// ] | ||
``` | ||
|
||
Because of this, Overture provides a `zip(with:)` helper, which takes a tranform function up front and is curried, so it can be composed with other functions using `pipe`. | ||
|
||
``` swift | ||
zip(with: User.init)(ids, emails, names) | ||
``` | ||
|
||
Overture also extends the notion of `zip` to work with optionals! It's an expressive way of combining multiple optionals together. | ||
|
||
``` swift | ||
let optionalId: Int? = 1 | ||
let optionalEmail: String? = "[email protected]" | ||
let optionalName: String? = "Blob" | ||
|
||
zip(optionalId, optionalEmail, optionalName) | ||
// Optional<(Int, String, String)>.some((1, "[email protected]", "Blob")) | ||
``` | ||
|
||
And `zip(with:)` lets us transform these tuples into other values. | ||
|
||
``` swift | ||
zip(with: User.init)(optionalId, optionalEmail, optionalName) | ||
// Optional<User>.some(User(id: 1, email: "[email protected]", name: "Blob")) | ||
``` | ||
|
||
Using `zip` can be an expressive alternative to `let`-unwrapping! | ||
|
||
``` swift | ||
let optionalUser = zip(with: User.init)(optionalId, optionalEmail, optionalName) | ||
|
||
// vs. | ||
|
||
let optionalUser: User? | ||
if let id = optionalId, let email = optionalEmail, let name = optionalName { | ||
optionalUser = User(id: id, email: email, name: name) | ||
} else { | ||
optionalUser = nil | ||
} | ||
``` | ||
|
||
## FAQ | ||
|
||
- **Should I be worried about polluting the global namespace with free functions?** | ||
|
@@ -336,15 +410,15 @@ let request = with(URLRequest(url: url), concat( | |
If you use [Carthage](https://github.com/Carthage/Carthage), you can add the following dependency to your `Cartfile`: | ||
|
||
``` ruby | ||
github "pointfreeco/swift-overture" ~> 0.2 | ||
github "pointfreeco/swift-overture" ~> 0.3 | ||
``` | ||
|
||
### CocoaPods | ||
|
||
If your project uses [CocoaPods](https://cocoapods.org), just add the following to your `Podfile`: | ||
|
||
``` ruby | ||
pod 'Overture', '~> 0.2' | ||
pod 'Overture', '~> 0.3' | ||
``` | ||
|
||
### SwiftPM | ||
|
@@ -353,7 +427,7 @@ If you want to use Overture in a project that uses [SwiftPM](https://swift.org/p | |
|
||
``` swift | ||
dependencies: [ | ||
.package(url: "https://github.com/pointfreeco/swift-overture.git", from: "0.2.0") | ||
.package(url: "https://github.com/pointfreeco/swift-overture.git", from: "0.3.0") | ||
] | ||
``` | ||
|
||
|
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
public func zip<A, B, C>( | ||
_ a: A?, | ||
_ b: B?, | ||
_ c: C? | ||
) | ||
-> (A, B, C)? { | ||
return zip(zip(a, b), c).map { ($0.0, $0.1, $1) } | ||
} | ||
|
||
public func zip<A, B, C, D>( | ||
with transform: @escaping (A, B, C) -> D | ||
) | ||
-> (A?, B?, C?) -> D? { | ||
return { zip($0, $1, $2).map(transform) } | ||
} | ||
|
||
public func zip<A, B, C, D>( | ||
_ a: A?, | ||
_ b: B?, | ||
_ c: C?, | ||
_ d: D? | ||
) | ||
-> (A, B, C, D)? { | ||
return zip(zip(a, b), c, d).map { ($0.0, $0.1, $1, $2) } | ||
} | ||
|
||
public func zip<A, B, C, D, E>( | ||
with transform: @escaping (A, B, C, D) -> E | ||
) | ||
-> (A?, B?, C?, D?) -> E? { | ||
return { zip($0, $1, $2, $3).map(transform) } | ||
} | ||
|
||
public func zip<A, B, C, D, E>( | ||
_ a: A?, | ||
_ b: B?, | ||
_ c: C?, | ||
_ d: D?, | ||
_ e: E? | ||
) | ||
-> (A, B, C, D, E)? { | ||
return zip(zip(a, b), c, d, e).map { ($0.0, $0.1, $1, $2, $3) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F>( | ||
with transform: @escaping (A, B, C, D, E) -> F | ||
) | ||
-> (A?, B?, C?, D?, E?) -> F? { | ||
return { zip($0, $1, $2, $3, $4).map(transform) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F>( | ||
_ a: A?, | ||
_ b: B?, | ||
_ c: C?, | ||
_ d: D?, | ||
_ e: E?, | ||
_ f: F? | ||
) | ||
-> (A, B, C, D, E, F)? { | ||
return zip(zip(a, b), c, d, e, f).map { ($0.0, $0.1, $1, $2, $3, $4) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F, G>( | ||
with transform: @escaping (A, B, C, D, E, F) -> G | ||
) | ||
-> (A?, B?, C?, D?, E?, F?) -> G? { | ||
return { zip($0, $1, $2, $3, $4, $5).map(transform) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F, G>( | ||
_ a: A?, | ||
_ b: B?, | ||
_ c: C?, | ||
_ d: D?, | ||
_ e: E?, | ||
_ f: F?, | ||
_ g: G? | ||
) | ||
-> (A, B, C, D, E, F, G)? { | ||
return zip(zip(a, b), c, d, e, f, g).map { ($0.0, $0.1, $1, $2, $3, $4, $5) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F, G, H>( | ||
with transform: @escaping (A, B, C, D, E, F, G) -> H | ||
) | ||
-> (A?, B?, C?, D?, E?, F?, G?) -> H? { | ||
return { zip($0, $1, $2, $3, $4, $5, $6).map(transform) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F, G, H>( | ||
_ a: A?, | ||
_ b: B?, | ||
_ c: C?, | ||
_ d: D?, | ||
_ e: E?, | ||
_ f: F?, | ||
_ g: G?, | ||
_ h: H? | ||
) | ||
-> (A, B, C, D, E, F, G, H)? { | ||
return zip(zip(a, b), c, d, e, f, g, h).map { ($0.0, $0.1, $1, $2, $3, $4, $5, $6) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F, G, H, I>( | ||
with transform: @escaping (A, B, C, D, E, F, G, H) -> I | ||
) | ||
-> (A?, B?, C?, D?, E?, F?, G?, H?) -> I? { | ||
return { zip($0, $1, $2, $3, $4, $5, $6, $7).map(transform) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F, G, H, I>( | ||
_ a: A?, | ||
_ b: B?, | ||
_ c: C?, | ||
_ d: D?, | ||
_ e: E?, | ||
_ f: F?, | ||
_ g: G?, | ||
_ h: H?, | ||
_ i: I? | ||
) | ||
-> (A, B, C, D, E, F, G, H, I)? { | ||
return zip(zip(a, b), c, d, e, f, g, h, i).map { ($0.0, $0.1, $1, $2, $3, $4, $5, $6, $7) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F, G, H, I, J>( | ||
with transform: @escaping (A, B, C, D, E, F, G, H, I) -> J | ||
) | ||
-> (A?, B?, C?, D?, E?, F?, G?, H?, I?) -> J? { | ||
return { zip($0, $1, $2, $3, $4, $5, $6, $7, $8).map(transform) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F, G, H, I, J>( | ||
_ a: A?, | ||
_ b: B?, | ||
_ c: C?, | ||
_ d: D?, | ||
_ e: E?, | ||
_ f: F?, | ||
_ g: G?, | ||
_ h: H?, | ||
_ i: I?, | ||
_ j: J? | ||
) | ||
-> (A, B, C, D, E, F, G, H, I, J)? { | ||
return zip(zip(a, b), c, d, e, f, g, h, i, j).map { ($0.0, $0.1, $1, $2, $3, $4, $5, $6, $7, $8) } | ||
} | ||
|
||
public func zip<A, B, C, D, E, F, G, H, I, J, K>( | ||
with transform: @escaping (A, B, C, D, E, F, G, H, I, J) -> K | ||
) | ||
-> (A?, B?, C?, D?, E?, F?, G?, H?, I?, J?) -> K? { | ||
return { zip($0, $1, $2, $3, $4, $5, $6, $7, $8, $9).map(transform) } | ||
} |
Oops, something went wrong.