将闭包数组减少为单个闭包
Reduce array of closures into single closure
假设我有一组闭包,它们都可以相互组合(即自同态,它们的输入和输出类型相同)。如何将这些闭包组合成一个闭包?
作为参考,我尝试设计如下内容。
struct MyType {
typealias MyClosure: (T) -> T
private var myClosures: [MyClosure] = [ ... ]
public var closure: MyClosure {
get {
return ? // somehow compose all of myClosures into a single closure here
}
}
}
我的第一个想法是使用 reduce
,就像 myClosures.reduce(STARTING) { a, b in b(a) }
,
但这需要提供一个起始值,然后连续对其应用闭包。我不想将闭包应用到任何东西(目前),只是将私有闭包列表合成一个 public 闭包,以后可以应用。鉴于 reduce
的方式是
定义,我希望这看起来像
myClosures.reduce(identity) { a, b in compose(a, b) }
func identity(_ input: T) { return input }
func compose(a: MyClosure, b: MyClosure) -> MyClosure { return b(a) }
但是b(a)
的类型是T
,不是(T) -> T
。如何做到这一点?这是处理闭包组合的更好方法吗?
编辑:我原来的回答误解了你的问题。但鉴于我原来的回答可能对未来的读者有用,我会把它留在底部。
您的 compose
功能即将实现! b(a)
无法编译,因为 MyClosure
没有占用另一个 MyClosure
。 b(a)
是 调用 闭包 ("function application")。不是组成。既然 compose
return 是一个闭包,为什么 return 不是一个闭包?典型的闭包在 Swift:
中看起来像这样
{ (param) in return doSomethingTo(param) }
所以让我们return那个!
return { (x) in return b(a(x)) }
这可以简化为:
{ b(a([=12=])) } // "return" can be omitted as well!
This page(除其他事项外)告诉您如何以及何时可以简化闭包语法。
原回答:
这里使用reduce
是正确的选择。归约操作是组合,所以我们先写一个compose
函数:
func compose<T>(_ x: @escaping (T) -> T, _ y: @escaping (T) -> T) -> (T) -> T {
{ y(x([=13=])) } // or { x(y([=13=])) } if you want it the other way
}
然后,我们reduce
。什么身份?身份是具有这些属性的东西:
compose(identity, anything) == anything
compose(anything, identity) == anything
那是什么功能?恒等函数!
所以我们得到:
func reduceClosures<T>(_ closures: [(T) -> T]) -> (T) -> T {
closures.reduce({ [=15=] }, compose)
}
假设我有一组闭包,它们都可以相互组合(即自同态,它们的输入和输出类型相同)。如何将这些闭包组合成一个闭包?
作为参考,我尝试设计如下内容。
struct MyType {
typealias MyClosure: (T) -> T
private var myClosures: [MyClosure] = [ ... ]
public var closure: MyClosure {
get {
return ? // somehow compose all of myClosures into a single closure here
}
}
}
我的第一个想法是使用 reduce
,就像 myClosures.reduce(STARTING) { a, b in b(a) }
,
但这需要提供一个起始值,然后连续对其应用闭包。我不想将闭包应用到任何东西(目前),只是将私有闭包列表合成一个 public 闭包,以后可以应用。鉴于 reduce
的方式是
定义,我希望这看起来像
myClosures.reduce(identity) { a, b in compose(a, b) }
func identity(_ input: T) { return input }
func compose(a: MyClosure, b: MyClosure) -> MyClosure { return b(a) }
但是b(a)
的类型是T
,不是(T) -> T
。如何做到这一点?这是处理闭包组合的更好方法吗?
编辑:我原来的回答误解了你的问题。但鉴于我原来的回答可能对未来的读者有用,我会把它留在底部。
您的 compose
功能即将实现! b(a)
无法编译,因为 MyClosure
没有占用另一个 MyClosure
。 b(a)
是 调用 闭包 ("function application")。不是组成。既然 compose
return 是一个闭包,为什么 return 不是一个闭包?典型的闭包在 Swift:
{ (param) in return doSomethingTo(param) }
所以让我们return那个!
return { (x) in return b(a(x)) }
这可以简化为:
{ b(a([=12=])) } // "return" can be omitted as well!
This page(除其他事项外)告诉您如何以及何时可以简化闭包语法。
原回答:
这里使用reduce
是正确的选择。归约操作是组合,所以我们先写一个compose
函数:
func compose<T>(_ x: @escaping (T) -> T, _ y: @escaping (T) -> T) -> (T) -> T {
{ y(x([=13=])) } // or { x(y([=13=])) } if you want it the other way
}
然后,我们reduce
。什么身份?身份是具有这些属性的东西:
compose(identity, anything) == anything
compose(anything, identity) == anything
那是什么功能?恒等函数!
所以我们得到:
func reduceClosures<T>(_ closures: [(T) -> T]) -> (T) -> T {
closures.reduce({ [=15=] }, compose)
}