Last active
August 2, 2023 04:46
-
-
Save BrunoCerberus/22475aaace747fe97373dc11c8976d53 to your computer and use it in GitHub Desktop.
Transform Operators
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
import Foundation | |
import Combine | |
// Helper function to print the description of the example before running it. | |
public func example(of description: String, action: () -> Void) { | |
print("\n——— Example of:", description, "———") | |
action() | |
} | |
// Simple struct to represent a coordinate with x and y values. | |
public struct Coordinate { | |
public let x: Int | |
public let y: Int | |
public init(x: Int, y: Int) { | |
self.x = x | |
self.y = y | |
} | |
} | |
// Function to determine the quadrant of a coordinate given its x and y values. | |
public func quadrantOf(x: Int, y: Int) -> String { | |
var quadrant = "" | |
switch (x, y) { | |
case (1..., 1...): | |
quadrant = "1" | |
case (..<0, 1...): | |
quadrant = "2" | |
case (..<0, ..<0): | |
quadrant = "3" | |
case (1..., ..<0): | |
quadrant = "4" | |
default: | |
quadrant = "boundary" | |
} | |
return quadrant | |
} | |
// A set to store subscriptions to Combine publishers. | |
var subscriptions = Set<AnyCancellable>() | |
// Example of using the "collect" operator on a publisher. | |
example(of: "collect") { | |
["A", "B", "C", "D", "E", "F"].publisher | |
.collect(2) | |
.sink( | |
receiveCompletion: { print($0) }, | |
receiveValue: { print($0) } | |
) | |
.store(in: &subscriptions) | |
} | |
// Example of using the "map" operator on a publisher to transform integers into their spelled-out representation. | |
example(of: "map") { | |
let formatter = NumberFormatter() | |
formatter.numberStyle = .spellOut | |
[123, 4, 56].publisher | |
.map { | |
formatter.string(for: NSNumber(integerLiteral: $0)) ?? "" | |
} | |
.sink( | |
receiveCompletion: { print($0) }, | |
receiveValue: { print($0) } | |
) | |
.store(in: &subscriptions) | |
} | |
// Helper function to log the quadrant of a coordinate. | |
func log(_ x: Int, _ y : Int) { | |
print("The coordinate at (\(x) and \(y) is in quadrant \(quadrantOf(x: x, y: y))") | |
} | |
// Example of using the "map" operator with key paths to extract specific properties of a Coordinate struct. | |
example(of: "map key paths") { | |
let publisher = PassthroughSubject<Coordinate, Never>() | |
publisher | |
.map(\.x, \.y) | |
.sink(receiveValue: log) | |
.store(in: &subscriptions) | |
publisher.send(Coordinate(x: 10, y: -8)) | |
publisher.send(Coordinate(x: 1, y: 5)) | |
} | |
// Example of using the "tryMap" operator to perform a throwing operation on a publisher's output. | |
example(of: "tryMap") { | |
Just("Directory name that does not exist") | |
.tryMap { try FileManager.default.contentsOfDirectory(atPath: $0) } | |
.sink( | |
receiveCompletion: { print($0) }, | |
receiveValue: { print($0) } | |
) | |
.store(in: &subscriptions) | |
} | |
// Example of using the "flatMap" operator to decode a list of integers into a string. | |
example(of: "flatMap") { | |
func decode(_ codes: [Int]) -> AnyPublisher<String, Never> { | |
Just( | |
codes | |
.compactMap { code in | |
guard (32...255).contains(code) else { return nil } | |
return String(UnicodeScalar(code) ?? " ") | |
} | |
.joined() | |
) | |
.eraseToAnyPublisher() | |
} | |
[72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33] | |
.publisher | |
.collect() | |
.flatMap(decode) | |
.sink(receiveValue: { print($0) }) | |
.store(in: &subscriptions) | |
} | |
// Example of using the "replaceNil" operator to replace nil values with a default value. | |
example(of: "replaceNil") { | |
["A", nil, "C"] | |
.publisher | |
.replaceNil(with: "B") | |
.sink(receiveValue: { print($0) }) | |
.store(in: &subscriptions) | |
} | |
// Example of using the "replaceEmpty(with:)" operator to replace an empty publisher with a default value. | |
example(of: "replaceEmpty(with:)") { | |
let empty = Empty<Int, Never>() | |
empty | |
.replaceEmpty(with: 1) | |
.sink( | |
receiveCompletion: { print($0) }, | |
receiveValue: { print($0) } | |
) | |
.store(in: &subscriptions) | |
} | |
// Example of using the "scan" operator to accumulate values and produce an array of intermediate results. | |
example(of: "scan") { | |
var dailyGainLoss: Int { .random(in: -10...10) } | |
let august2019 = (0..<22) | |
.map { _ in dailyGainLoss } | |
.publisher | |
august2019 | |
.scan(50) { latest, current in | |
max(0, latest + current) | |
} | |
.collect() | |
.sink(receiveValue: { print($0) }) | |
.store(in: &subscriptions) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment