这里它说,“注意:_意味着“我不关心这个值”,但来自JavaScript,我不明白这意味着什么。

我可以打印这些函数的唯一方法是在参数前使用下划线:

func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(7, 3))
print(divmod(5, 2))
print(divmod(12,4))

如果没有下划线,我必须这样写,以避免任何错误:

func divmod(a: Int, b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(a: 7, b: 3))
print(divmod(a: 5, b: 2))
print(divmod(a: 12,b: 4))

我不明白这个下划线的用法。什么时候、如何以及为什么要使用这些下划线?


当前回答

不同的用例之间有一些细微差别,但通常下划线表示“忽略这个”。


当声明一个新函数时,一个下划线告诉Swift参数在被调用时不应该有标签-这就是你所看到的情况。更完整的函数声明如下所示:

func myFunc(label name: Int) // call it like myFunc(label: 3)

"label"是一个参数标签,在调用函数时必须出现。(从Swift 3开始,默认情况下所有参数都需要标签。)"name"是你在函数中使用的参数的变量名。简短的形式是这样的:

func myFunc(name: Int) // call it like myFunc(name: 3)

这是一种快捷方式,允许您对外部参数标签和内部参数名称使用相同的单词。它等价于func myFunc(name name: Int)。

如果你想让你的函数在没有参数标签的情况下也可以被调用,你可以使用下划线_使标签为nothing/忽略。(在这种情况下,如果您希望能够使用参数,则必须提供一个内部名称。)

func myFunc(_ name: Int) // call it like myFunc(3)

在赋值语句中,下划线表示“不要赋值给任何东西”。如果你想调用一个返回结果但不关心返回值的函数,你可以使用这个。

_ = someFunction()

或者,就像你链接到的文章中那样,忽略返回元组的一个元素:

let (x, _) = someFunctionThatReturnsXandY()

在编写实现某些已定义函数类型的闭包时,可以使用下划线忽略某些参数。

PHPhotoLibrary.performChanges( { /* some changes */ },
    completionHandler: { success, _ in // don't care about error
        if success { print("yay") }
    })

类似地,当声明一个采用协议或覆盖超类方法的函数时,可以使用_作为参数名来忽略参数。由于协议/超类也可能定义参数没有标签,因此您甚至可以在一行中以两个下划线结束。

class MyView: NSView {
    override func mouseDown(with _: NSEvent) {
        // don't care about event, do same thing for every mouse down
    }
    override func draw(_ _: NSRect) {
        // don't care about dirty rect, always redraw the whole view
    }
}

有点类似于后两种风格:当使用绑定局部变量/常量的流控制结构时,可以使用_来忽略它。例如,如果你想迭代一个序列而不需要访问它的成员:

for _ in 1...20 { // or 0..<20
    // do something 20 times
}

如果你在switch语句中绑定元组情况,下划线可以作为通配符,就像这个例子(从Swift编程语言中的一个缩写而来):

switch somePoint { // somePoint is an (Int, Int) tuple
case (0, 0):
    print("(0, 0) is at the origin")
case (_, 0):
    print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
    print("(0, \(somePoint.1)) is on the y-axis")
default:
    print("(\(somePoint.0), \(somePoint.1)) isn't on an axis")
}

最后一件不太相关的事情,但我将包括它,因为(正如评论所指出的)它似乎把人们引向这里:标识符中的下划线-例如var _foo, func do_the_thing(), struct Stuff_ -对Swift没有什么特别的意义,但在程序员中有一些用途。

名字中的下划线是一种风格选择,但在Swift社区中并不受欢迎,因为Swift社区对类型使用UpperCamelCase,对所有其他符号使用lowerCamelCase有很强的约定。

在符号名前面加上下划线是一种风格约定,在历史上用于区分私有/仅供内部使用的符号与导出的API。然而,Swift对此有访问修饰符,所以这个约定在Swift中通常被视为非惯用的。

一些带有双下划线前缀的符号(func __foo())潜伏在苹果的sdk的深处:这些是(Obj)C符号,使用NS_REFINED_FOR_SWIFT属性导入Swift。当苹果想要做一个(Obj)C API的“更Swifty”版本时,他们就会使用这个方法——例如,把一个类型不可知的方法变成一个泛型方法。他们需要使用导入的API来使完善的Swift版本工作,所以他们使用__来保持它可用,同时对大多数工具和文档隐藏它。

其他回答

不同的用例之间有一些细微差别,但通常下划线表示“忽略这个”。


当声明一个新函数时,一个下划线告诉Swift参数在被调用时不应该有标签-这就是你所看到的情况。更完整的函数声明如下所示:

func myFunc(label name: Int) // call it like myFunc(label: 3)

"label"是一个参数标签,在调用函数时必须出现。(从Swift 3开始,默认情况下所有参数都需要标签。)"name"是你在函数中使用的参数的变量名。简短的形式是这样的:

func myFunc(name: Int) // call it like myFunc(name: 3)

这是一种快捷方式,允许您对外部参数标签和内部参数名称使用相同的单词。它等价于func myFunc(name name: Int)。

如果你想让你的函数在没有参数标签的情况下也可以被调用,你可以使用下划线_使标签为nothing/忽略。(在这种情况下,如果您希望能够使用参数,则必须提供一个内部名称。)

func myFunc(_ name: Int) // call it like myFunc(3)

在赋值语句中,下划线表示“不要赋值给任何东西”。如果你想调用一个返回结果但不关心返回值的函数,你可以使用这个。

_ = someFunction()

或者,就像你链接到的文章中那样,忽略返回元组的一个元素:

let (x, _) = someFunctionThatReturnsXandY()

在编写实现某些已定义函数类型的闭包时,可以使用下划线忽略某些参数。

PHPhotoLibrary.performChanges( { /* some changes */ },
    completionHandler: { success, _ in // don't care about error
        if success { print("yay") }
    })

类似地,当声明一个采用协议或覆盖超类方法的函数时,可以使用_作为参数名来忽略参数。由于协议/超类也可能定义参数没有标签,因此您甚至可以在一行中以两个下划线结束。

class MyView: NSView {
    override func mouseDown(with _: NSEvent) {
        // don't care about event, do same thing for every mouse down
    }
    override func draw(_ _: NSRect) {
        // don't care about dirty rect, always redraw the whole view
    }
}

有点类似于后两种风格:当使用绑定局部变量/常量的流控制结构时,可以使用_来忽略它。例如,如果你想迭代一个序列而不需要访问它的成员:

for _ in 1...20 { // or 0..<20
    // do something 20 times
}

如果你在switch语句中绑定元组情况,下划线可以作为通配符,就像这个例子(从Swift编程语言中的一个缩写而来):

switch somePoint { // somePoint is an (Int, Int) tuple
case (0, 0):
    print("(0, 0) is at the origin")
case (_, 0):
    print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
    print("(0, \(somePoint.1)) is on the y-axis")
default:
    print("(\(somePoint.0), \(somePoint.1)) isn't on an axis")
}

最后一件不太相关的事情,但我将包括它,因为(正如评论所指出的)它似乎把人们引向这里:标识符中的下划线-例如var _foo, func do_the_thing(), struct Stuff_ -对Swift没有什么特别的意义,但在程序员中有一些用途。

名字中的下划线是一种风格选择,但在Swift社区中并不受欢迎,因为Swift社区对类型使用UpperCamelCase,对所有其他符号使用lowerCamelCase有很强的约定。

在符号名前面加上下划线是一种风格约定,在历史上用于区分私有/仅供内部使用的符号与导出的API。然而,Swift对此有访问修饰符,所以这个约定在Swift中通常被视为非惯用的。

一些带有双下划线前缀的符号(func __foo())潜伏在苹果的sdk的深处:这些是(Obj)C符号,使用NS_REFINED_FOR_SWIFT属性导入Swift。当苹果想要做一个(Obj)C API的“更Swifty”版本时,他们就会使用这个方法——例如,把一个类型不可知的方法变成一个泛型方法。他们需要使用导入的API来使完善的Swift版本工作,所以他们使用__来保持它可用,同时对大多数工具和文档隐藏它。

func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

func divmod(a: Int, b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

_是参数名的占位符。在你的例子中,你以不同的方式调用它们,在第二个函数中,你需要写参数名a: 1。

Swift的函数名约定是funcName(param1:param2:),它需要_作为占位符来创建函数名。

在第一个名字里,名字是

divmod(_:_:)

而第二个是

divmod(a:b:)

Since Swift 3, specifying parameter names on function calls has become compulsory - even for the first. So, because that could cause huge problem to code written in swift 2, you can use a underscore at the declaration to prevent having to write the parameter name on call. So in this case, it is saying "don't care about the external parameter name". Where the external parameter name is what you call the parameters outside the function (on call) not inside. These external parameter names are called argument labels. http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some-thoughts/ ... see how the parameter is given two names? well the first is where the underscore is going.Hope this helps, and do ask if still confused.