Swift 使用紧凑映射进行快速语法解释
我在检查代码时发现了以下代码:Swift 使用紧凑映射进行快速语法解释,swift,higher-order-functions,Swift,Higher Order Functions,我在检查代码时发现了以下代码: override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { return super.layoutAttributesForElements(in: rect)? .compactMap { $0.copy() as? ParallaxLayoutAttributes }
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return super.layoutAttributesForElements(in: rect)?
.compactMap { $0.copy() as? ParallaxLayoutAttributes }
.compactMap(prepareAttributes)
}
private func prepareAttributes(attributes: ParallaxLayoutAttributes) -> ParallaxLayoutAttributes {
// Lot of code doing stuff with attributes
return attributes
}
所以,实际上我想问的是,这个compact函数声明如下:
@inlinable public func compactMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
这完全让我心烦意乱,因为,prepareAttributes
函数声明如下(必须传递参数):
那么,为什么要编译上面的代码,以及如何准确地编译.compactMap(prepareAttributes)
在调用
.compactMap(prepareAttributes)
中未传递prepareAttributes
函数的参数时运行。在调用.compactMap(prepareAttributes)
时,将函数prepareAttributes
作为闭包传递给compactMap
。由于prepareAttributes
接受一个类型与compactMap
的闭包变量匹配的输入参数,编译器可以自动推断它需要将$0
传递给prepareAttributes
所以本质上,.compactMap(prepareAttributes)
是
.compactMap {prepareAttributes(attributes: $0) }
与map
相同的行为的一个简单示例是将map
映射到一个类型上,然后将该类型传递到一个init中,您可以将该类型写成.map{MyType(input:$0)}
或简化为.map(MyType.init)
这里比较棘手的一点是,compactMap只接受一个参数,即闭包。函数实际上是一种闭包。通过传入函数名,可以告诉compactMap生成对函数的调用,将源集合中的对象作为参数传入该函数,并期望返回新类型的对象。@Duncac这也是我试图得到的结果,但是我想你的解释更清楚:)那太好了,谢谢你的详细回答:)我想知道在哪里可以找到所有的语法“速记”,它们“缩短”了代码,因为有时候它看起来有点confusing@EvgeniyKleban不客气。遗憾的是,这些都是“隐藏的”宝藏,通常没有相关文档。苹果的Swift iBook深入介绍了闭包语法,以及缩短调用/传递闭包的大多数不同方式。我似乎记得它涵盖了这个案子,但我已经有一段时间没有读过了。我建议看那里)相关的(如果不是重复的话):。
private func prepareAttributes(attributes: ParallaxLayoutAttributes) -> ParallaxLayoutAttributes
.compactMap {prepareAttributes(attributes: $0) }
struct MyInt {
let value: Int
init(value: Int) {
self.value = value
}
}
let ints = [1,2,3]
let myInts = ints.map(MyInt.init) // same as `ints.map { MyInt(value: $0) }