【问题标题】:Swift closure with parameter syntax带有参数语法的 Swift 闭包
【发布时间】:2021-02-07 01:00:09
【问题描述】:

我正在快速学习,但我被参数语法的疯狂闭包困住了。以下是执行此操作的“正确方法”。

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 的调用中而不是在 sip 定义中指定 brew 。像这样的...

sip( on: beer( brew.porter )

这样啤酒闭包在被调用时就被参数化了。这不是更具可读性和实用性吗?为什么不是这样?有没有一种语法可以做到这一点?

另外,不应该有一种方法可以编写一个带有可变参数的 sip() 方法,以便它可以接收啤酒或杜松子酒吗?怎么样?

闭包令人困惑!

【问题讨论】:

  • 你想让sip做什么?你希望关闭做什么?现在你正在传递一个带有参数的闭包,sip 通过传递一个.porter 来调用它。你提供的你想要的例子对我来说没有意义。看起来您想将闭包和参数都传递给它;目前尚不清楚为什么。

标签: swift closures


【解决方案1】:

另外,不应该有一种方法可以编写一个带有可变参数的 sip() 方法,以便它可以接收啤酒或杜松子酒吗?

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

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

sip(on: beer(brew.porter))

然后声明一个sip可能的。

现在,执行beer(brew.porter) 将调用beer 闭包。 beer 闭包返回Void,而Void 不能传递给sip,这样就行不通了。你的直觉可能会说“为什么beer(brew.porter) 不能返回另一个闭包,当不带参数调用时,它会喝啤酒和波特酒?”恭喜,你发现了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) }) 

【讨论】:

  • 谢谢!我没有将闭包的目的理解为基本上可以传递给其他动词的动词。啤酒和杜松子酒不是动词。它们是“什么”而不是“如何”。所以我的例子让我误解了闭包的作用。我想我现在明白了。再次感谢。
猜你喜欢
  • 2016-02-01
  • 2020-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-02
  • 1970-01-01
  • 2021-12-30
相关资源
最近更新 更多