杂谈 - 最近的一些心得体会和感想 (二)

这篇文章其实已经写好有一段时间了,但是最近忙如狗,一直没找到时间发出来。最近开始应该压力减缓,也能找到时间开始重新更新了!OYOY~

上一篇杂谈,今天来说说在迁移到 PromiseKit 6 的过程中的一些体会。

Swift 编译器的原罪

为了让异步逻辑稍微清楚一些,避免回调地狱,在公司的项目里我们使用了 PromiseKit。没错,这个框架的作者正是写了 HomeBrew 然后被 Google 华丽地以“不会翻转二叉树”为理由拒了的 Max Howell 大大。代码质量和接口设计都是相当有保证的。

我们之前使用的是 version 5,一个很严重的问题是关于闭包的类型推断。说实话,这没办法责备说是 PromiseKit 的问题,更多地还是 Swift 自身类型系统和现在编译器的不足。我们都知道,Swift 是可以自动进行类型推断的,也就是说,你可以写这样的代码:

let a = 1

var hugeNumber: Float {
    return .greatestFiniteMagnitude
}

let f = hugeNumber

在上面,我们没有指定 af 的类型,但是编译器可以从上下文 (以及标准库) 中为我们推断出 它们分别是 IntFloat。另外,在 hugeNumber 的实现中,我们也可以直接写 .greatestFiniteMagnitude 而不需要完整的 Float.greatestFiniteMagnitude,这也得益于类型推断,因为我们想要返回的显然是一个 Float 值。

So far so good。但是一旦我们引入闭包以后,事情就稍微复杂一些。比如说我们有这两个确定类型的闭包:

let block1: (Int) -> Void = { param in
    print("block1")
}

let block2: (Int) -> Int = { param in
    print("block2")
    return 0
}

然后有两个对应的同名方法,它们接受一个函数作为参数:

func receiveBlock(b: (Int) -> Void) {
    print("receiveBlock void")
    b(1)
}

func receiveBlock<T>(b: (Int) -> T) -> T {
    print("receiveBlock T")
    return b(1)
}

在 Swift 中,类型也是函数签名的一部分,所以这里我们可以声明两个类型不同的函数。因为带有泛型的后者的签名更加 generic,而接受 (Int) -> Void 类型的前者更加具体。在使用的时候当我们不加区别地把 block1block2 传入 receiveBlock 时:

```swift

top Created with Sketch.