Swift 带参数语法的闭包

Swift closure with parameter syntax

我正在学习 swift,但我一直坚持使用带参数语法的疯狂闭包。以下是执行此操作的“正确方法”。

enum Brew: Int {
    case lager
    case barleyWine
    case porter
}

let beer = { (kind: Brew) -> Void in
    print( "\(kind), smooth!")
}

let gin = { () -> Void in
    print("gin & juice")
}

func sip( on drink: () -> Void ) {
    print("Sip...")
    drink()
}

func sip( on drink: (Brew) -> Void ) {
    print("Sip...")
    drink(brew.porter)
}

sip( on: beer )
sip( on: gin )

这会打印...

Sip...
porter, smooth!
Sip...
gin & juice

但是,这对我来说意义不大。每当我用啤酒调用 sip() 时,它的编码方式就假定它是搬运工。似乎我应该能够在对 sip 的调用中指定 brew 而不是在 sip 定义中。像这样...

sip( on: beer( brew.porter )

这样啤酒闭包在被调用时被参数化。这不是更具可读性和实用性吗?为什么不是这样呢?有实现此功能的语法吗?

此外,是否应该有一种方法可以编写一个带有可变参数的 sip() 方法,以便它可以喝啤酒或杜松子酒?怎么样?

闭包令人困惑!

Also, shouldn't there be a way to write one sip() method with variable parameters so that it can take beer OR gin?

现在,beergin 是不同类型的闭包(beer 接受参数而 gin 不接受),这就是为什么你需要两个sip 的重载 - 一个来处理每种类型。想象一下,如果有一个 sip 可以同时接受它们,会发生什么。它如何知道是否传递参数?

另一方面,如果您的最终目标是这样的:

sip(on: beer(brew.porter))

然后声明单个 sip 可能的。

现在,执行 beer(brew.porter) 将调用 beer 闭包。 beer 闭包 returns VoidVoid 不能传递到 sip,所以那是行不通的。你的直觉可能会说“为什么不能 beer(brew.porter) return 另一个闭包,当没有参数调用时,用波特啤酒喝啤酒?”恭喜,您发现了 currying.

您可以更改 beer 来做到这一点:

let beer = { (kind: Brew) -> (() -> Void) in // a closure that returns a closure!
    // return { () -> Void in print("\(kind), smooth!") }
    return { print( "\(kind), smooth!") } // short-hand
}

现在你只需要这个 sip:

func sip( on drink: () -> Void ) {
    print("Sip...")
    drink()
}

但在现实世界中,您通常无法更改 beer(因为这是别人的代码,或者没有意义)。在这种情况下,您必须更改调用 sip:

的方式
// "{}" indicates a closure! You are putting the closure call "beer(brew.porter)" inside another closure.
sip(on: { beer(brew.porter) })