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

Mic*_*der 131 swift

在这里它说:"注意:_意思是"我不关心那个价值",但是来自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))
Run Code Online (Sandbox Code Playgroud)

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

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))
Run Code Online (Sandbox Code Playgroud)

我不明白这个下划线用法.何时,如何以及为何使用这些下划线?

ric*_*ter 299

不同的用例有一些细微差别,但通常下划线意味着"忽略这个".


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

func myFunc(label name: Int) // call it like myFunc(label: 3)
Run Code Online (Sandbox Code Playgroud)

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

func myFunc(name: Int) // call it like myFunc(name: 3)
Run Code Online (Sandbox Code Playgroud)

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

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

func myFunc(_ name: Int) // call it like myFunc(3)
Run Code Online (Sandbox Code Playgroud)

在赋值语句中,下划线表示"不分配给任何东西".如果要调用返回结果但不关心返回值的函数,可以使用此方法.

_ = someFunction()
Run Code Online (Sandbox Code Playgroud)

或者,与您链接的文章一样,忽略返回元组的一个元素:

let (x, _) = someFunctionThatReturnsXandY()
Run Code Online (Sandbox Code Playgroud)

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

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

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)

与最后两种样式有些相关:当使用绑定局部变量/常量的流控制构造时,您可以使用_忽略它.例如,如果要迭代序列而不需要访问其成员:

for _ in 1...20 { // or 0..<20
    // do something 20 times
}
Run Code Online (Sandbox Code Playgroud)

如果你在一个switch语句结合元组的情况下,下划线可以作为通配符,在这个例子中(从一个缩短的雨燕编程语言):

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")
}
Run Code Online (Sandbox Code Playgroud)

这似乎不太相关的最后一两件事,但我会因为包括(通过评论指出的),似乎在这里带领人们:下划线标识符-例如var _foo,func do_the_thing(),struct Stuff_-表示没有什么特别的斯威夫特,但有几个用途在程序员中间.

名称中的下划线是样式选择,但在Swift社区中不是首选,后者具有关于对类型使用UpperCamelCase和对所有其他符号使用lowerCamelCase的强烈约定.

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

与双下划线前缀几个符号(func __foo())潜伏在苹果公司的软件开发工具包的深处:这些(的OBJ)C符号使用导入斯威夫特NS_REFINED_FOR_SWIFT属性.当Apple想要制作一个"更加Swifty"版本的(Obj)C API时,Apple会使用它 - 例如,将类型无关的方法变成泛型方法.他们需要使用导入的API来使精炼的Swift版本工作,因此他们使用它__来保持它可用,同时将其隐藏在大多数工具和文档中.


Moj*_*ini 24

除了接受的答案之外,其中一个用例_是您需要在代码中编写一个长数字

更易读的数字

这不是一个简单的人类可读的:

let x = 1000000000000
Run Code Online (Sandbox Code Playgroud)

? 您可以添加_数字以使其更具人类可读性:

let x = 1_000_000_000_000
Run Code Online (Sandbox Code Playgroud)

下划线接口

您可能会在 Swift 中遇到接口以_. 虽然他们在技术上宣布public,但以下划线开头不是认为这个包的公共接口的一部分。我们可能会在任何版本中删除或更改它们,恕不另行通知,包括次要版本。

例如,官方 Swift Collections 存储库中的@_exportedImport更多示例

?? 干脆不要使用它们,或者您应该手动跟踪更改。


Cas*_*lie 5

从Swift 3开始,在函数调用上指定参数名称已成为必需-甚至对于第一个。因此,由于这可能会对swift 2中编写的代码造成巨大问题,因此可以在声明中使用下划线,以防止在调用时必须写入参数名称。因此,在这种情况下,就是说“不在乎外部参数名称”。外部参数名称是您在函数外部(调用时)而不是内部调用的参数。这些外部参数名称称为参数标签。http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some-thoughts/ ...看到参数是如何给两个名字的?好首先是下划线的去向。希望这会有所帮助,并询问是否仍然感到困惑。


dav*_*000 5

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)
}
Run Code Online (Sandbox Code Playgroud)

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

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

在第一个名字中,名字是

divmod(_:_:)
Run Code Online (Sandbox Code Playgroud)

而第二个是

divmod(a:b:)
Run Code Online (Sandbox Code Playgroud)