无法将 Swift 2.2 柯里化为未来的 Swift 格式

Cannot translate Swift 2.2 currying to future Swift format

我有以下柯里化函数,我收到一个 XCode 警告,说 柯里化函数语法将在 Swift 的未来版本中被删除;使用单个参数列表 ,但建议的修复不起作用(它只是将参数组合到一个函数调用中)。我正在尝试转换为新格式,但我不明白它是如何工作的。下面的 beginFetchWithCompletionHandler 函数期望 handleDownload 具有 (data : NSData?, error : NSError?) 的参数签名。

fetcher.beginFetchWithCompletionHandler(handleDownload)

我也想传入一个整数,如下:

fetcher.beginFetchWithCompletionHandler(handleDownload(0))

以下柯里化函数完美运行(但给出警告):

func handleDownload(iCount : Int)(data : NSData?, error : NSError?) -> Void {
    print(iCount)
    print(data!.length)
}

这是我试过的方法,但出现错误,"Expression resolves to an unused function":

func handleDownload2(iCount:Int) -> (NSData?, NSError?) -> Void {
    return { (data: NSData?, error: NSError?) -> Void in {
            // received image
            print(iCount)
            print(data!.length)
        }
    }
}

里面的大括号写错了,应该是:

func handleDownload2(iCount:Int) -> (NSData?, NSError?) -> Void {
    return { (data: NSData?, error: NSError?) -> Void in
        // received image
        print(iCount)
        print(data!.length)
    }
}

被接受的Swift进化提案SE-0002 - Removing currying func declaration syntax指出:

We remove support for multiple argument patterns in func declarations, reducing the grammar for func-signature to allow only one argument clause. For migration purposes, existing code that uses currying declaration syntax can be transformed to explicitly return a closure instead:

  // Before:
  func curried(x: Int)(y: String) -> Float {
    return Float(x) + Float(y)!
  }

  // After:
  func curried(x: Int) -> (String) -> Float {
    return {(y: String) -> Float in
      return Float(x) + Float(y)!
    }
  }

因此,Martin R为了解决你的代码给出的答案是正确的:

func handleDownload2(iCount: Int) -> (NSData?, NSError?) -> Void {
    return { (data: NSData?, error: NSError?) -> Void in
        // received image
        print(iCount)
        print(data!.length)
    }
}

但是请注意,您可以更简洁:

func handleDownload2(iCount: Int) -> (NSData?, NSError?) -> Void {
    return { (data, error) in
        // received image
        print(iCount)
        print(data!.length)
    }
}

此处,dataerror 的类型由 handleDownload2 函数的 return 类型隐式给出:(NSData?, NSError?) -> Void.


尽管出于可读性的考虑我不推荐它,但使用 shorthand argument names:

可以使您的代码更加简洁
func handleDownload2(iCount: Int) -> (NSData?, NSError?) -> Void {
    return {
        // received image
        print(iCount)
        print([=13=]!.length)
    }
}

此外,我有时会在使用闭包时尽量明确,因为它可以帮助我快速设置正确的 return 类型:

func handleDownload2(iCount: Int) -> (NSData?, NSError?) -> Void {
    let innerBlock: (NSData?, NSError?) -> Void = { (data, error) in
        // received image
        print(iCount)
        print(data!.length)
    }
    return innerBlock
}