Why Do I Need Underscores in Swift

Why do I need underscores in swift?

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.

What's the _ underscore representative of in Swift References?

Both answers were correct but I want to clarify a little bit more.

_ is used to modify external parameter name behavior for methods.

In Local and External Parameter Names for Methods section of the documentation, it says:

Swift gives the first parameter name in a method a local parameter name by default, and gives the second and subsequent parameter names both local and external parameter names by default.

On the other hand, functions by default don't have external parameter names.

For example, we have this foo() method defined in class Bar:

class Bar{
func foo(s1: String, s2: String) -> String {
return s1 + s2;
}
}

When you call foo(), it is called like bar.foo("Hello", s2: "World").

But, you can override this behavior by using _ in front of s2 where it's declared.

func foo(s1: String, _ s2: String) -> String{
return s1 + s2;
}

Then, when you call foo, it could be simply called like bar.foo("Hello", "World") without the name of the second parameter.

Back to your case, runAction is a method because it's associated with type SKNode, obviously. Thus, putting a _ before parameter action allows you to call runAction without an external name.

Update for Swift 2.0

Function and method now work the same way in terms of local and external argument name declaration.

Functions are now called by using external parameter name by default, starting at 2nd parameter. This rule only applies to pure Swift code.

So, by providing an _ in front of a function, the caller won't have to specify external parameter name, just like what you would do for a method.

What does the underscore mean before a variable in Swiftui in an init()?

The underscored variable name refers to the underlying storage for the Binding struct. This is part of a language feature called Property Wrappers.

Given one variable declaration, @Binding var momentDate: Date, you can access three variables:

  • self._momentDate is the Binding<Date> struct itself.
  • self.momentDate, equivalent to self._momentDate.wrappedValue, is a Date. You would use this when rendering the date in the view's body.
  • self.$momentDate, equivalent to self._momentDate.projectedValue, is also the Binding<Date>. You would pass this down to child views if they need to be able to change the date.

For Binding, the "projected value" ($) is just self, and the difference between _ and $ is only in the access level. However, other property wrappers may project a different type of value (see the @SmallNumber example in the language guide).

Assigning a Variable to an Underscore in Swift

This test shows that the object is created and then destroyed when the object goes out of scope:

class ToDoItem {
var title = ""

init(title: String) {
self.title = title
}

deinit {
print("deinit \(title)")
}
}

func test() {
print("test")

_ = ToDoItem(title: "First")
_ = ToDoItem(title: "Second")

print("end test")
}

func callTest() {
print("calling test()...")
test()
print("back from test()")
}

callTest()

Output:

calling test()...
test
end test
deinit Second
deinit First
back from test()

Extended test:

func test() {
print("test")

_ = ToDoItem(title: "Item 1")
for i in 2...4 {
_ = ToDoItem(title: "Item \(i)")
}
_ = ToDoItem(title: "Item 5")

print("end test")
}
calling test()...
test
deinit Item 2
deinit Item 3
deinit Item 4
end test
deinit Item 5
deinit Item 1
back from test()

Notice that items 2, 3 and 4 are deinitialized as they go out of scope in each loop. Items 1 and 5 are deinitialized when they go out of scope when test() completes.


Inside of an App

As Dmitry Plotnikov noted in his answer, the above is true only in a Swift Playground. In an app, the results are:

calling test()...
test
deinit Item 1
deinit Item 2
deinit Item 3
deinit Item 4
deinit Item 5
end test
back from test()

That tells us:

  1. The objects are created.
  2. They are freed immediately.

What do _:_: and similar combinations of the colon and underscore mean in Swift?

The underscore indicates that there is no external parameter name for the function. Apple's Swift Documentation talks about this concept in terms of when you're writing your own functions.

Take the case where you write this function (from the documentation):

func sayHello(to person: String, and anotherPerson: String) -> String { ... }

If you were to use the function you would write the following:

sayHello(to: "Bill", and: "Ted")

The signature for this would be sayHello(to:and:).
However, what if we wanted to use the function as sayHello("Bill", "Ted")? How would we indicate that we didn't want an external parameter name? Well that's where the underscore comes in. We could rewrite the function as:

func sayHello(person: String, _ anotherPerson: String) -> String { ... }

Note the first parameter doesn't need the _, but subsequent ones will. The first is inferred to have no parameter name. This makes the method signature for this call sayHello(_:_:) because you as the caller don't have a named parameter.

Update Swift 3.0:

Swift 3.0 treats all parameters equally. The first parameter now requires an underscore to indicate the absense of an external parameter name. In the above example of having sayHello("Bill", "Ted") at the call site, your corresponding function or method declaration would have to be

func sayHello(_ person: String, _ anotherPerson: String) -> String { ... }

Note the addition of the underscore before the internal parameter name 'person'.

What is _: in Swift telling me?

The _ is used to define that the parameter is not named

If you have multiple _ it states that you do not need to name the parameters in your function call

func myFunc(name:String, _ age:String){
}

myFunc(“Milo", "I'm a really old wizard")

If you do not use the underscore you would use

myFunc(“Milo”, age: "I'm a really old wizard")

The _ is not necessary for function calls. It is just used to indicate that something does not need to have a name.

In regards to how you would refer to your function, You would not have to pass any name for the function call.

But since you also don’t define a parameter type this seems to me like an invalid example (it at least doesn’t work in Xcode 7 with Swift 2.0)

Edit:

Since Swift 3.0

myFunc(name: “Milo”, age: "I'm a really old wizard")

Should be used

Variable declaration with underscore

The first examples are essentially creating properties that are publicly readable but privately writable.

The second set of code does not do the same thing as the first set.

The proper way to write this code is:

private (set) var name: String // no need for the !
private (set) var studentID: Int // no need for the !

init(name: String, studentID: Int) {
self.name = name
self.studentID = studentID
}

This makes the properties readable by outside users but only settable by the class. This is what the 1st set of code implements but in a much more verbose and needless manner.

The use of underscore is just a naming convention carried over from Objective-C when creating private instance variables.

Personally, I'd avoid videos and tutorials that use the 1st set of code.



Related Topics



Leave a reply



Submit