【问题标题】:Swift syntax explanation with compact map使用紧凑映射的 Swift 语法解释
【发布时间】:2020-08-29 17:35:03
【问题描述】:

我在检查代码时确实找到了以下代码:

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]

在此示例中,我们只传递函数,不带参数:

.compactMap(prepareAttributes)

这完全颠覆了我的想法,因为,prepareAttributes 函数声明是这样的(你必须通过参数):

private func prepareAttributes(attributes: ParallaxLayoutAttributes) -> ParallaxLayoutAttributes

那么,为什么上面的代码可以编译,.compactMap(prepareAttributes) 到底是怎么编译的? 当您没有为 prepareAttributes 函数传递参数时运行?

【问题讨论】:

标签: swift higher-order-functions


【解决方案1】:

在调用.compactMap(prepareAttributes) 中,您将函数prepareAttributes 作为闭包传递给compactMap。由于prepareAttributes 采用单个输入参数,其类型与compactMap 的闭包变量匹配,编译器可以自动推断它需要将$0 传递给prepareAttributes

所以本质上,.compactMap(prepareAttributes)

的简写
.compactMap {prepareAttributes(attributes: $0) }

map 相同的行为的一个简单示例是经常使用的map 类型,然后您将其传递给init,您可以将其写为.map { MyType(input: $0) } 或简化为.map(MyType.init)

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) }

【讨论】:

  • 这里的棘手之处在于 compactMap 采用单个参数,即 closure。函数实际上是一种闭包。通过传入函数的名称,您告诉 compactMap 生成对函数的调用,将源集合中的对象作为参数传递给该函数,并期望返回新类型的对象。
  • @DuncanC 这也是我想要达到的,但我想你的解释更清楚:)
  • 太好了,感谢您的详细回答:) 我想知道在哪里可以找到所有这些语法“速记”,“缩短”代码,因为有时它看起来有点令人困惑
  • @EvgeniyKleban 不客气。可悲的是,其中大部分都是“隐藏”的宝石,通常没有关于它们的文档。
  • Apple 的 Swift iBook 深入介绍了闭包语法,以及可以缩短调用/传递闭包的大多数不同方法。我似乎记得它涵盖了这个案例,但我已经有一段时间没有阅读它了。我建议看那里)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多