Why do I need underscores in swift?

后端 未结 4 611
伪装坚强ぢ
伪装坚强ぢ 2020-11-30 16:51

Here it says, \"Note: the _ means “I don’t care about that value”\", but coming from JavaScript, I don\'t understand what that means.

The only way I can

相关标签:
4条回答
  • 2020-11-30 17:11

    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.

    0 讨论(0)
  • 2020-11-30 17:13

    There are a few nuances to different use cases, but generally an underscore means "ignore this".


    When declaring a new function, an underscore tells Swift that the parameter should have no label when called — that's the case you're seeing. A fuller function declaration looks like this:

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

    "label" is an argument label, and must be present when you call the function. (And since Swift 3, labels are required for all arguments by default.) "name" is the variable name for that argument that you use inside the function. A shorter form looks like this:

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

    This is a shortcut that lets you use the same word for both external argument label and internal parameter name. It's equivalent to func myFunc(name name: Int).

    If you want your function to be callable without parameter labels, you use the underscore _ to make the label be nothing/ignored. (In that case you have to provide an internal name if you want to be able to use the parameter.)

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

    In an assignment statement, an underscore means "don't assign to anything". You can use this if you want to call a function that returns a result but don't care about the returned value.

    _ = someFunction()
    

    Or, like in the article you linked to, to ignore one element of a returned tuple:

    let (x, _) = someFunctionThatReturnsXandY()
    

    When you write a closure that implements some defined function type, you can use the underscore to ignore certain parameters.

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

    Similarly, when declaring a function that adopts a protocol or overrides a superclass method, you can use _ for parameter names to ignore parameters. Since the protocol/superclass might also define that the parameter has no label, you can even end up with two underscores in a row.

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

    Somewhat related to the last two styles: when using a flow control construct that binds a local variable/constant, you can use _ to ignore it. For example, if you want to iterate a sequence without needing access to its members:

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

    If you're binding tuple cases in a switch statement, the underscore can work as a wildcard, as in this example (shortened from one in 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")
    }
    

    One last thing that's not quite related, but which I'll include since (as noted by comments) it seems to lead people here: An underscore in an identifier — e.g. var _foo, func do_the_thing(), struct Stuff_ — means nothing in particular to Swift, but has a few uses among programmers.

    Underscores within a name are a style choice, but not preferred in the Swift community, which has strong conventions about using UpperCamelCase for types and lowerCamelCase for all other symbols.

    Prefixing or suffixing a symbol name with underscore is a style convention, historically used to distinguish private/internal-use-only symbols from exported API. However, Swift has access modifiers for that, so this convention generally is seen as non-idiomatic in Swift.

    A few symbols with double-underscore prefixes (func __foo()) lurk in the depths of Apple's SDKs: These are (Obj)C symbols imported into Swift using the NS_REFINED_FOR_SWIFT attribute. Apple uses that when they want to make a "more Swifty" version of an (Obj)C API — for example, to make a type-agnostic method into a generic method. They need to use the imported API to make the refined Swift version work, so they use the __ to keep it available while hiding it from most tools and documentation.

    0 讨论(0)
  • 2020-11-30 17:25

    In addition to the accepted answer, one of the use cases of _ is when you need to write a long number in code

    More readable number

    This is not easy human readable:

    let x = 1000000000000
    

    You can add _ in the number to make it more human readable:

    let x = 1_000_000_000_000
    
    0 讨论(0)
  • 2020-11-30 17:28
    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)
    }
    

    The _ is a placeholder for the parameter name. In your example, you call them differently, in the second function, you need to write the parameter name a: 1.

    Swift's function name convention is funcName(param1:param2:), and it needs the _ as a placeholder to create the name of the function.

    In the first name, the name is

    divmod(_:_:)
    

    Whereas the second is

    divmod(a:b:)
    
    0 讨论(0)
提交回复
热议问题