【问题标题】:Understanding syntax of closure with no return type理解没有返回类型的闭包语法
【发布时间】:2016-12-31 22:10:13
【问题描述】:

我在这里第一次接触到 swift,我偶然发现了一个闭包语句,根据我目前对闭包编写方式的理解,这对我来说没有多大意义。这实际上是一个由两部分组成的问题,因为我也不太了解使用此闭包进行条件绑定背后的意图/解释。

我被抛出的代码块是这样的:

 FIRAuth.auth()?.createUser(withEmail: email, password: password) {
    (user, error) in if let error = error {
        print(error.localizedDescription)
        return
    }
}

我的理解是闭包需要根据文档定义 (something1, something2) -> () 指定返回类型,所以从上面的代码中,这是否意味着 swift 可以通过不包括 -> () 来推断 void 返回?

我的假设是条件绑定语句只是说'如果错误 arg 被传递到这个闭包中,那么打印错误?

请在您的解释中使用尽可能详细的信息,以便我进一步理解。干杯!

【问题讨论】:

  • 您发布的代码的上下文是什么?是闭包的内容吗? (在一组{}内?)
  • @MattSanford 我认为您仍然缺少结束语}
  • 你是对的@Alexander

标签: swift closures conditional-binding


【解决方案1】:

以下都是等价的

func foo1() -> () { }
func foo2() -> () { return () }
func foo3() -> () { return Void() }
func foo4() -> () { return }

func foo5() -> Void { }
func foo6() -> Void { return () }
func foo7() -> Void { return Void() }
func foo8() -> Void { return }

func foo9() { }
func foo10() { return () }
func foo11() { return Void() }
func foo12() { return }

print(type(of: foo1))  // (()) -> ()
// ...
print(type(of: foo5))  // (()) -> ()
// ...
print(type(of: foo9))  // (()) -> ()
// ...

如果没有返回 type 提供给函数(/closure),则推断出空元组 type(类型别名为 Void)。然而,我们可以明确地提供这个返回type,或者作为()type),或者Void。来自the language guide - functions

没有返回值的函数

函数不需要定义返回类型。 ...

...

严格来说,这个版本的greet(person:) 函数确实 仍然返回一个值,即使没有定义返回值。 没有定义返回类型的函数返回一个特殊的值 输入Void。这只是一个空元组,写成()

相反,如果函数块末尾没有给出return,则与显式返回一个空元组的实例相同,即()价值)。这也可以简单地写成return

【讨论】:

  • 哇,我不知道有这么多方法可以写同样的东西。这非常有帮助
  • @jtbandes 它看起来确实有点奇怪,但我相信它遵循一般约定:闭包(参数和返回类型)的组合类型注释中的参数类型注释用括号括起来,这甚至是必需的,例如当在闭包的主体中显式包含类型注释时(例如{ (arg: Int) -> Int in 2*arg })。或者,也许您提到了另一个怪异,而我没有抓住重点?感谢您的反馈!
  • 我的意思是你可以说 foo1 接受 no 参数,所以我希望 () -> (),但它的打印好像它接受一个 @ 类型的参数987654336@。这些通常是可以互换的。可能与为github.com/apple/swift-evolution/blob/master/proposals/…所做的工作有关
  • @jtbandes 啊,我明白了,我同意。似乎当前类型注释明确选择将无参数情况视为显式的单个空元组参数。我想这可能被视为有些差异,例如let closure1: () -> Int = { ... } 是允许的,而let closure2: Int -> Int = { ... } 是不允许的(因为closure 的类型被表示为(()) -> Int,那么我们应该在声明时用括号括起来(),但这会很疯狂,所以更好的方法是让特殊的 void-argument 案例简单地具有类型 () -> ...)。
  • @MattSanford 很乐意为您提供帮助。
【解决方案2】:

() 是空元组。 Swift 中的Void 只是() 的类型别名。如果函数或闭包未指定返回类型,则假定为 ()

为避免混淆,(user, error) in 应独占一行:

 FIRAuth.auth()?.createUser(withEmail: email, password: password) { user, error in
    if let error = error {
        print(error.localizedDescription)
        return
    }
 }

我建议使用guard 声明来强制提前返回:

 FIRAuth.auth()?.createUser(withEmail: email, password: password) { user, error in
    guard error == nil else {
        print(error!.localizedDescription)
        return
    }

     // There's no error, carry on...
 }

【讨论】:

  • 在该函数的更下方,我还有其他事情要做,所以如果实际上存在错误,我想结束执行。 (user, error) in 上线会引起混乱吗? (我原始问题的第二部分)
猜你喜欢
  • 1970-01-01
  • 2021-03-30
  • 2021-01-06
  • 2015-11-23
  • 2015-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多