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))
我不明白这种强调用法。何时,如何以及为何使用这些下划线?
答案 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 _foo
,func 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