5 ms·
Swift has both external and internal parameter names for functions. This is to make API design more readable, easier to parse through. For example, you can hav
by Watabou 9y ago
Swift has both external and internal parameter names for functions. This is to make API design more readable, easier to parse through.
For example, you can have a function like so:
func greet(with greeting: String, to personName: String) {
print("\(greeting), \(personName)!")
}
In the above code, "with" and "to" are external names, and are only available when calling the function but are not available inside the function itself. So you would call this function like so:
greet(with: "Hello", to: "Bob")
Now if you want to exclude the external name to call the functions, you use the "_" syntax. So you're right that it denotes an unused parameter. In this case, it's an unused external parameter name.
- derefr 9y agoIs there a parse-time reason that they required the "_" syntax, rather than simply: func greet(greeting: String, personName: String) { print("\(greeting), \(personName)!") }
- thramp 9y agoIt's a side effect of labeled arguments. The caller would use the function greet as `greet(greeting: "Hello", personName: "Alice")`.
- masklinn 9y agoThe reason is that named parameters is the default, so in your case greeting and personName are both "internal" and "external" names. "_ greeting" sets the external name to _ (aka positional) and the internal name to "greeting" instead.
- saghm 9y agoHaving never used Swift, it feels like the syntax is being optimized for the less-common case; are named parameters considered the "default" choice in Swift, and is using different external names so common that it's worth cluttering the syntax for functions without external parameters in order to make the their own syntax easier?
- jurip 9y agoYou can argue if it's useful or not on its own, but it makes sense when you consider that Swift is compatible with Objective-C. In Objective-C, that function would be a method like -(void) greetWith:(NSString *)greeting to:(NSString *)personName and you'd call it like [self greetWith:@"Hello" to:@"Bob"] Swift's external/internal parameters are built to allow the same style as was used with Objective-C and easy bridging. Swift's APIs tend to be terser than Objective-C ones, though.
- ridiculous_fish 9y agoNamed parameters are very much the default in Swift. Positional parameters are rare exceptions. The internal/external name divide often works out beautifully. For example, let's equip Double with a multiply-add. An idiomatic Swift signature: extension Double { func multiply(by multiplier:Double, adding summand:Double) -> Double { return self * multiplier + summand } } print(3.multiply(by:4, adding:5)) Erase punctuation and you have: func multiply by multiplier adding summand print 3 multiply by 4 adding 5 The caller sees an action (multiply by, adding), the callee sees nouns (multiplier, summand). It's fantastically readable.
- kybernetikos 9y agoThe javascript equivalent would be something like Number.prototype.multiply = function({by:multiplier, adding:summand = 0}) { return this * multiplier + summand } console.log((3).multiply({by: 4, adding: 5})) But of course, javascript APIs are hardly ever written like that. I think it's interesting how the norms of your ecosystem and very small differences in ergonomics in expression make a big difference in behaviour.
- masklinn 9y ago> are named parameters considered the "default" choice in Swift Most definitely yes. In fact it used to be that the first parameter was implicitly positional (in Swift 2 IIRC), this was removed to make all parameters named by default. And do note that you can provide a single label for a parameter, it will be used as both "internal" and "external" names: func foo(bar: String) { print(bar); } foo(bar: "3") func baz(qux quux: String) { print(quux); } baz(qux: "4") > and is using different external names so common Also yes, it's absolutely ubiquitous, if only because that's the one way to provide "positional" parameter.
- manmal 9y agoI think it likely that labeled arguments were introduced mainly for Objective-C interoperability.
- Watabou 9y agoFor Obj-C fans though, named arguments are one of its best features. Yes, more verbose, easy to decipher, and led to great API design. For the first versions of Swift, they actually had two versions. For functions (i.e not functions inside classes), you didn't have to have named arguments for the first parameter, but you did for methods (functions inside classes). They explicitly added it for Swift 3 to make it more consistent with method. I think I like the consistency more, but I do agree "_" is ugly. I don't have an idea of what else they could do though. I don't want Swift to make the parameter names optional, since no one would use it (like in Python, I rarely see named arguments being used)
- superlopuh 9y agoThat's not quite right, the special case was the `init`s, where all the parameters were named, whereas the first parameter of `func`s was not named. This kind of made sense, as you could put the name of the first parameter as part of the function name, which is impossible for an initializer. In the end, they normalised it to all parameters being named. On a side note, I like the _, it's a clear signal of not caring about something and doesn't take up a lot of visual space.
- Grustaf 9y agoRather because it fits the Cocoa philosophy, that both Swift and ObjC subscribe to. I think argument labels are great, makes the code much more readable.