Skip to content

Instantly share code, notes, and snippets.

@Amzd
Last active May 16, 2023 19:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Amzd/478c4c593a6b8c8566516738bd17e54c to your computer and use it in GitHub Desktop.
Save Amzd/478c4c593a6b8c8566516738bd17e54c to your computer and use it in GitHub Desktop.
Appending Closures, eg a shorthand to create one new closure that calls two closures.
// MARK: Appending closures `a + b`
/// Append closures, lhs first.
public func + <I>(lhs: @escaping (I) -> Void, rhs: @escaping (I) -> Void) -> ((I) -> Void) {
return {
lhs($0)
rhs($0)
}
}
/// Append closures, lhs first.
public func + <I0, I1>(lhs: @escaping (I0, I1) -> Void, rhs: @escaping (I0, I1) -> Void) -> ((I0, I1) -> Void) {
return {
lhs($0, $1)
rhs($0, $1)
}
}
/// Append closures, lhs first.
public func + <I0, I1, I2>(lhs: @escaping (I0, I1, I2) -> Void, rhs: @escaping (I0, I1, I2) -> Void) -> ((I0, I1, I2) -> Void) {
return {
lhs($0, $1, $2)
rhs($0, $1, $2)
}
}
/// Append closures, lhs first.
public func + <I0, I1, I2, I3>(lhs: @escaping (I0, I1, I2, I3) -> Void, rhs: @escaping (I0, I1, I2, I3) -> Void) -> ((I0, I1, I2, I3) -> Void) {
return {
lhs($0, $1, $2, $3)
rhs($0, $1, $2, $3)
}
}
// MARK: Appending closures `a += b`
/// Appends closure to lhs.
public func += <I>(lhs: inout (I) -> Void, rhs: @escaping (I) -> Void) {
let copy = lhs
lhs = {
copy($0)
rhs($0)
}
}
/// Appends closure to lhs.
public func += <I0, I1>(lhs: inout (I0, I1) -> Void, rhs: @escaping (I0, I1) -> Void) {
let copy = lhs
lhs = {
copy($0, $1)
rhs($0, $1)
}
}
/// Appends closure to lhs.
public func += <I0, I1, I2>(lhs: inout (I0, I1, I2) -> Void, rhs: @escaping (I0, I1, I2) -> Void) {
let copy = lhs
lhs = {
copy($0, $1, $2)
rhs($0, $1, $2)
}
}
/// Appends closure to lhs.
public func += <I0, I1, I2, I3>(lhs: inout (I0, I1, I2, I3) -> Void, rhs: @escaping (I0, I1, I2, I3) -> Void) {
let copy = lhs
lhs = {
copy($0, $1, $2, $3)
rhs($0, $1, $2, $3)
}
}
// MARK: Appending closures `a += b` where a is an optional
/// Appends closure to lhs.
public func += <I>(lhs: inout ((I) -> Void)?, rhs: @escaping (I) -> Void) {
let copy = lhs
lhs = {
copy?($0)
rhs($0)
}
}
/// Appends closure to lhs.
public func += <I0, I1>(lhs: inout ((I0, I1) -> Void)?, rhs: @escaping (I0, I1) -> Void) {
let copy = lhs
lhs = {
copy?($0, $1)
rhs($0, $1)
}
}
/// Appends closure to lhs.
public func += <I0, I1, I2>(lhs: inout ((I0, I1, I2) -> Void)?, rhs: @escaping (I0, I1, I2) -> Void) {
let copy = lhs
lhs = {
copy?($0, $1, $2)
rhs($0, $1, $2)
}
}
/// Appends closure to lhs.
public func += <I0, I1, I2, I3>(lhs: inout ((I0, I1, I2, I3) -> Void)?, rhs: @escaping (I0, I1, I2, I3) -> Void) {
let copy = lhs
lhs = {
copy?($0, $1, $2, $3)
rhs($0, $1, $2, $3)
}
}
// MARK: Appending closures with AdditiveArithmetic results
/// Sum outcomes of lhs and rhs
public func + <I, O: AdditiveArithmetic>(lhs: @escaping (I) -> O, rhs: @escaping (I) -> O) -> ((I) -> O) {
return {
lhs($0) + rhs($0)
}
}
/// Sum outcomes of lhs and rhs
public func += <I, O: AdditiveArithmetic>(lhs: inout (I) -> O, rhs: @escaping (I) -> O) {
let copy = lhs
lhs = {
copy($0) + rhs($0)
}
}
/// Subtract rhs from lhs
public func - <I, O: AdditiveArithmetic>(lhs: @escaping (I) -> O, rhs: @escaping (I) -> O) -> ((I) -> O) {
return {
lhs($0) - rhs($0)
}
}
/// Subtract rhs from lhs
public func -= <I, O: AdditiveArithmetic>(lhs: inout (I) -> O, rhs: @escaping (I) -> O) {
let copy = lhs
lhs = {
copy($0) - rhs($0)
}
}
func doSomething(with _: String) {}
func example() {
struct Example {
var callback: (String) -> Void
}
var example = Example(callback: {
doSomething(with: $0)
})
// +
var example2 = Example(callback: doSomething(with:) + doSomething(with:))
var example3 = Example(callback: doSomething + doSomething)
// +=
example.callback += {
doSomething(with: $0)
}
example2.callback += doSomething(with:)
// combined
example3.callback += doSomething + doSomething + doSomething
}
func arithmeticExample() {
// Can't think of when this is useful xd
// note that both closures are called with the same input,
// it is not a pipeline!
let add30 = {
$0 + 30.0
}
let dividingBy2 = {
$0 / 2.0
}
let sumOfResults = add30 + dividingBy2
print(sumOfResults(0)) // (0 + 30) + (0 / 2) = 30
print(sumOfResults(10)) // (10 + 30) + (10 / 2) = 45
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment