为什么我需要快速下划线?

时间:2016-09-21 21:48:52

标签: swift

Here它说,"注意:_表示“我不关心这个价值”",但是来自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))

我不明白这种强调用法。何时,如何以及为何使用这些下划线?

4 个答案:

答案 0 :(得分:259)

不同的用例存在一些细微差别,但通常下划线表示"忽略这个"。

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

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

"标签"是一个参数标签,在调用该函数时必须存在。 (从Swift 3开始,默认情况下所有参数都需要标签。)" name"是您在函数内使用的该参数的变量名称。较短的表格如下所示:

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

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

如果希望在没有参数标签的情况下调用函数,可以使用下划线_使标签无任何/忽略。 (在这种情况下,如果您希望能够使用该参数,则必须提供内部名称。)

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") }
    })

同样,在声明采用协议或覆盖超类方法的函数时,可以使用_参数 names 来忽略参数。由于协议/超类也可能定义参数没有标签,因此您甚至可以连续使用两个下划线。

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语句中绑定元组个案,则下划线可以作为通配符使用,如本示例所示(从The Swift Programming Language中的缩写):

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 _foofunc do_the_thing()struct Stuff_ - 对Swift没有任何意义,但在程序员中有一些用处。

名称中的下划线是样式选择,但在Swift社区中不是首选,后者对于使用UpperCamelCase进行类型而使用较强的约定,而对于所有其他符号使用lowerCamelCase。

使用下划线对符号名称进行前缀或后缀是一种样式约定,历史上用于区分私有/仅内部使用符号和导出的API。但是,Swift具有访问修饰符,因此这种约定在Swift中通常被视为非惯用语。

一些带有双下划线前缀(func __foo())的符号潜伏在Apple的SDK的深处:这些是使用NS_REFINED_FOR_SWIFT属性导入Swift的(Obj)C符号。当他们想要制作更多的Swifty&#34; (Obj)C API的版本 - 例如,to make a type-agnostic method into a generic method。他们需要使用导入的API来使精炼的Swift版本工作,因此他们使用__使其保持可用,同时将其隐藏在大多数工具和文档中。

答案 1 :(得分:3)

从Swift 3开始,在函数调用中指定参数名称已成为必需 - 即使是第一个。因此,因为这可能会给使用swift 2编写的代码带来很大的问题,所以您可以在声明中使用下划线来防止在调用时编写参数名称。所以在这种情况下,它说“不关心外部参数名称”。其中外部参数名称是您调用函数外部的参数(在通话中)不在内部。这些外部参数名称称为参数标签。 http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some-thoughts/ ...看看参数如何给出两个名字?好吧,第一个是下划线要去的地方。希望这有帮助,并且确实要问是否仍然困惑。

答案 2 :(得分:2)

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:)

答案 3 :(得分:2)

除了可接受的答案外,_的一种用例是当您需要在代码中写长数字时

可读性更好的数字

这不容易理解:

let x = 1000000000000

您可以在数字中添加_,以提高可读性:

let x = 1_000_000_000_000