Skip to content

Commit d161715

Browse files
Add flatMap(:)
1 parent 56075c9 commit d161715

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Convenient methods like `resolve(favoring:)` and `merge(coalesce:)` also provide
2020

2121
Transform a `Delta` value to a different `Delta` value using `map(:)` or `asyncMap(:)`.
2222

23-
`Delta` works well when working with optionals, providing initializers to create a `Delta` from optionals as well as alternative methods like `compactMap(:)` and `compactMerge(coalesce:)` to produce optionals.
23+
`Delta` works well when working with optionals, providing initializers to create a `Delta` from optionals as well as alternative methods like `flatMap(:)`, `compactMap(:)`, and `compactMerge(coalesce:)` to produce optionals.
2424

2525
The `Delta` type also conforms to all standard protocols (depending on the conformances of it’s `Element` type):
2626

Sources/LightTableDelta/Delta.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,46 @@ public extension Delta where Element: ~Copyable {
105105
}
106106
}
107107

108+
/// Returns a delta containing the results of mapping the given closure over the delta’s elements, or `nil`, if the closure returns `nil` for all elements.
109+
///
110+
/// The notable difference to `compactMap(:)` is that this method does not return `nil` when `transform` returns `nil` for only one element in the `transition` case.
111+
/// Instead, a `source` or `target` delta is returned, matching the non-`nil` return value.
112+
@inlinable
113+
consuming func flatMap<T: ~Copyable, E>(
114+
_ transform: (consuming Element) throws(E) -> T?
115+
) throws(E) -> Delta<T>? {
116+
switch consume self {
117+
case .source(let source):
118+
guard let source = try transform(source) else {
119+
return nil
120+
}
121+
return .source(source)
122+
case .target(let target):
123+
guard let target = try transform(target) else {
124+
return nil
125+
}
126+
return .target(target)
127+
case .transition(let source, let target):
128+
let source = try transform(source)
129+
let target = try transform(target)
130+
return if source != nil && target != nil {
131+
.transition(source: source!, target: target!)
132+
}
133+
else if let source {
134+
.source(source)
135+
}
136+
else if let target {
137+
.target(target)
138+
}
139+
else {
140+
nil
141+
}
142+
}
143+
}
144+
108145
/// Returns a delta containing the results of mapping the given closure over the delta’s elements, or `nil`, if the closure returns `nil` for any element.
146+
///
147+
/// The notable difference to `flatMap(:)` is that this method also returns `nil` when `transform` returns `nil` for only one element in the `transition` case.
109148
@inlinable
110149
consuming func compactMap<T: ~Copyable, E>(
111150
_ transform: (consuming Element) throws(E) -> T?

0 commit comments

Comments
 (0)