Skip to content

Instantly share code, notes, and snippets.

@BrunoCerberus
Last active August 2, 2023 04:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BrunoCerberus/22475aaace747fe97373dc11c8976d53 to your computer and use it in GitHub Desktop.
Save BrunoCerberus/22475aaace747fe97373dc11c8976d53 to your computer and use it in GitHub Desktop.
Transform Operators
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