Swift中`in`关键字的含义是什么?

78

我正试图实现来自parse.com的一些代码,我注意到在void之后有一个关键字in

我被难住了,这是什么?第二行你看到了Void in

PFUser.logInWithUsernameInBackground("myname", password:"mypass") {
  (user: PFUser?, error: NSError?) -> Void in
  if user != nil {
    // Do stuff after successful login.
  } else {
    // The login failed. Check error to see why.
  }
}

文档中没有对此进行说明。我知道 in 关键字在 for 循环中使用。

有人能确认一下吗?


4
在 "in" 之前是闭包的签名,在 "in" 之后是闭包的主体。 - user1971598
1
http://www.apeth.com/swiftBook/ch02.html#_anonymous_functions - matt
请在The Swift Programming Language中查找“Closure Expression Syntax”。 - Daniel T.
3个回答

111
在一个命名函数中,我们在func声明行中声明参数和返回类型。
func say(s:String)->() {
    // body
}

在匿名函数中,没有 func 声明行 - 它是匿名的!因此,我们将其替换为在函数体开头处使用的 in 行。

{
    (s:String)->() in
    // body
}

那是匿名函数的完整形式。但是Swift有一系列规则,允许在特定情况下省略返回类型、参数类型,甚至是参数名称和整个in语句。


谢谢Matt,我简直不敢相信我错过了那个。感谢你指出来。 - Martin

22
在Swift闭包语法中,关键字in用作函数类型和闭包内部函数体之间的分隔符。其他用户已经很好地回答了in的作用是什么,总结起来如下:

{ /参数和类型/ in /函数体/ }

对于那些想知道“但为什么要使用关键字in?”的人,这是苹果高级Swift编译器工程师Joe Groff在Swift论坛上分享的历史背景:

It's my fault, sorry. In the early days of Swift, we had a closure syntax that was very similar to traditional Javascript:

func (arg: -> Type, arg: Type) -> Return { ... }

While this is nice and regular syntax, it is of course also very bulky and awkward if you're trying to support expressive functional APIs, such as map/filter on collections, or if you want libraries to be able to provide closure-based APIs that feel like extensions of the language.

Our earliest adopters at Apple complained about this, and mandated that we support Ruby-style trailing closure syntax. This is tricky to fit into a C-style syntax like Swift's, and we tried many different iterations, including literally Ruby's {|args| } syntax, but many of them suffered from ambiguities or simply distaste and revolt from our early adopters. We wanted something that still looked like other parts of the language, but which could be parsed unambiguously and could span the breadth of use cases from a fully explicit function signature to extremely compact.

We had already taken in as a keyword, we couldn't use -> like Java does because it's already used to denote the return type, and we were concerned that using => like C# would be too visually confusing. in made xs.map { x in f(x) } look vaguely like for x in xs { f(x) }, and people hated it less than the alternatives.

*本文格式和强调为我所加。感谢Nikita Belov在Swift论坛上的帖子,对我的理解有所帮助。

*格式和强调为我所加。感谢Nikita Belov在Swift论坛上的帖子,帮助我理解这一点。


2
“而且人们对它的厌恶程度比其他选择要少。”这是我今天所需要的验证。在这里,“in”是一个副词,试图代替一个介词。使用“from”会更有意义。 - user18365424
2
不想太苛刻,但“in”在这里明显是作为介词使用的(否则它会修饰哪个“动词”呢?)。此外,“from”也是错误的:表达式f(x)来自参数x,而不是反过来。 - Tyg13
1
我从文档中最喜欢的收获是:“当将闭包作为内联闭包表达式传递给函数或方法时,始终可以推断出参数类型和返回类型。因此,当闭包用作函数或方法参数时,您永远不需要以完整形式编写内联闭包。” - Scott T. Miller

19

闭包表达式的语法一般具有以下形式:

闭包表达式语法


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接