This is a fairly simple Swift wrapper that adds operator support to pointfreeco
's swift-overture library.
Its operators are inspired by their swift-prelude library.
Add the following to the dependencies
section of your Package.swift
file:
.package(url: "https://github.com/randomeizer/swift-rhapsody", from: "0.5.0")
Then add Rhapsody
as a dependency for your target:
.target(name: "YourTarget", dependencies: [
.product(name: "Rhapsody", package: "swift-rhapsody"),
])
Rhapsody exports the Overture
library, so you can simply replace Overture
with Rhapsody
in your code.
Let's say we have three basic functions:
let increment = { (x: Int) in x + 1 }
let double = { (x: Int) in x * 2 }
let decrement = { (x: Int) in x - 1 }
We can forward-compose them using the >>>
operator:
import Rhapsody
// forward-compose
let h = increment >>> double
let i = h >>> decrement
print(h(1)) // 4
print(i(1)) // 3
You can use any standard Overture
functions in the same way:
import Rhapsody
let h = pipe(increment, double)
print(h(1)) // 4
Or, combine a series of operators:
import Rhapsody
let j = 1 |> increment >>> double >>> decrement
print(j) // 3
Or, combine Overture
functions and Rhapsody
operators:
import Rhapsody
let add = { (x: Int, y: Int) in x + y }
// forward-compose
let h = curry(add)(5) >>> double
The library exports the following operators:
This operator chains two functions together where the output of the first function is the input of the second function.
let f = { (x: Int) in x + 1 }
let g = { (x: Int) in "\(x)!" }
let h = f >>> g
print(h(1)) // "2!"
This operator chains two functions together where the output of the second function is the input of the first function.
let f = { (x: Int) in x + 1 }
let g = { (x: Int) in "\(x)!" }
let h = g <<< f
print(h(1)) // "2!"
There are a couple of variations of this operator. The essentially chains functions where the input and output types are the same.
let f = { (x: Int) in x + 1 }
let g = { (x: Int) in x * 2 }
let h = f <> g
print(h(1)) // 4
The second variation is for functions that take an inout
parameter and return Void
:
var x = 1
let f = { (x: inout Int) in x += 1 }
let g = { (x: inout Int) in x *= 2 }
let h = f <> g
h(&x)
print(x) // 4
The third variation is for functions that take a single reference type parameter and return Void
:
final class Box<A> {
var value: A
init(_ value: A) {
self.value = value
}
}
let f = { (box: Box<Int>) in box.value += 1 }
let g = { (box: Box<Int>) in box.value *= 2 }
let h = f <> g
let box = Box(1)
h(box)
print(box.value) // 4
There are a few variations of this operator. The first takes the left-hand side and passes it as the input to the right-hand side, returning the result:
let f = { (x: Int) in x + 1 }
let result = 1 |> f
print(result) // 2
The second variation is for functions that take an inout
parameter and return Void
:
var x = 1
let f = { (x: inout Int) in x += 1 }
x |> f
print(x) // 2
The third variation is for functions that take a single reference type parameter and return Void
:
final class Box<A> {
var value: A
init(_ value: A) {
self.value = value
}
}
let f = { (box: Box<Int>) in box.value += 1 }
let box = Box(1)
box |> f
print(box.value) // 2