假设我有一个闭包数组,这些闭包可以彼此组合(例如,自同态,它们的输入和输出类型是相同的)。如何将这些闭包组合成一个单独的闭包?
作为参考,我试图设计如下的东西。
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,àla myClosures.reduce(STARTING) { a, b in b(a) },但这需要提供一个初始值,然后依次对其应用闭包。我不想将闭包应用于任何东西(目前为止),而只是将闭包的私有列表合成成一个单独的公开闭包,可以在以后应用。考虑到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。如何才能做到这一点?这是一个更好的方式来进行闭幕式构图吗?
发布于 2020-05-09 16:57:07
编辑:我最初的回答误解了你的问题所在。但鉴于我最初的答案可能对未来的读者有用,我会把它放在最下面。
您的compose函数就快到了!b(a)不编译,因为MyClosure不使用另一个MyClosure。b(a)正在调用闭包(“函数应用程序”)。不是构图。既然compose返回一个闭包,为什么不返回一个闭包呢?在Swift中,典型的闭包如下所示:
{ (param) in return doSomethingTo(param) }所以让我们把它还回去!
return { (x) in return b(a(x)) }这可以简化为:
{ b(a($0)) } // "return" can be omitted as well!此页 (以及其他事情)告诉您如何以及何时可以简化闭包语法。
原来的答案:
在这里使用reduce是正确的选择。还原操作是组合操作,所以让我们首先编写一个compose函数:
func compose<T>(_ x: @escaping (T) -> T, _ y: @escaping (T) -> T) -> (T) -> T {
{ y(x($0)) } // or { x(y($0)) } 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({ $0 }, compose)
}https://stackoverflow.com/questions/61700254
复制相似问题