In Swift 2, it appears that the first parameter name is not always required when calling a function. Now in Swift 3, the first parameter name is required when calling the function. For example:
func frobnicate(runcible: String) {
print("Frobnicate: \(runcible)")
}
Swift 2.2 allowed the function to be called by simply typing:
Frobnicate("Station")
Swift 3 seems to be requiring that we use the first parameter names of methods such as:
Frobnicate(runcible:"Station")
Is this the case with Swift 3 for all functions and methods or just certain situations?
Yes, this is right. Swift is fixing a language inconsistency this way (this was always required for initializers).
If you don't want to use the external parameter name, just remove it explicitly:
func frobnicate(_ runcible: String) {
print("Frobnicate: \(runcible)")
}
You can read the full rationale in Swift Evolution 0046
You can read The Swift Programming Language (Swift 3) in i-Book. Also you can check this out in WWDC 2016: What's New in Swift
In Swift 3, by default, functions use their parameter names as labels for their arguments. Write a custom argument label before the parameter name, or write _ to use no argument label.
fun greet(_ person: String, on day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")
or
// This also works with Swift 2
fun addThreeNumber(_ first: Int, _ second: Int, _ third: Int) {
print(first+second+third)
}
addThreeNumber(1, 2, 3)
Exactly. In Swift 3.0, it's mandatory to write parameter names for all the parameters (including the first parameter). Parameter name is the one which is used inside the function implementation body.
func frobnicate(runcible: String) {
print("Frobnicate: \(runcible)")
}
By default, the external parameter label is same as the parameter name, if you don't specify any parameter label explicitly. Parameter label is the one which is used to pass the arguments while calling the function. If you need, for better clarity purpose, you can also specify external parameter labels explicitly. Example below-
func frobnicate(runcibleExternalLabel runcible: String) {
print("Frobnicate: \(runcible)")
}
If you want to skip the external parameter label while calling the function, just prepend a "_" before the parameter name.
func frobnicate(_ runcible: String) {
print("Frobnicate: \(runcible)")
}
Yes Swift 3 requires you to send First Parameter Label.
Please refer Swift 3 changes
The reason you want labels for parameters is so other code can supply parameters in any order.
Without labels, when you call the function the parameters are anonymous and you cannot be certain if you have supplied them in the wrong order.
Place labels in front of the parameters and code tools can do a much better job at catching errors us humans put in.
The underscore is just a way to cope with the transition from legacy code; method names including an Implicit first parameter. You should change any underscores that migration adds to your code to an explicit parameter label. You know it makes sense.
Related
This question already has an answer here:
Swift "with" keyword
(1 answer)
Closed 3 years ago.
Example:
func student(of name: String) -> String {
.
.
.
}
In that context, it's merely part of a method signature. To my knowledge, of is not a word that's used in Swift. To utilize that method, you'd type:
student(of: "<Student's name here>") and it would return a string.
If you omitted of from the signature above (func student(name: String) -> String), the method would be called as follows:
student(name: "Student's name here")
Lastly, if you changed the signature to put an underscore in front of the parameter, like so func student(_ name: String) -> String, you'd call the method as follows:
student("Student's name here")
In this case, "of" is the label for the argument called "name".
If you were to call this function, it would be
student(of: "Mathematics")
However inside the student function, you would get it's value with "name"
func student(of name: String) -> String {
print(name)
// TODO: Do something and return
}
Just a suggestion, IMHO "of" is not very descriptive of what the function does or what "of" represents (is "of" an id? The name of the student?).
Swift has a concept of external as well as internal parameter name. External parameter names are used to make the function signature more readable where as Internal parameter names are used for usage inside the function.
External parameter names are optional. If only one parameter name is provided, that name is used as both External and Internal. An External parameter name for the first parameter is required. If at any stage, you don't want to specify an External parameter, you can replace it with _.
Consider the following example:
func myFunctionToPrintDetailsOfStudentWithFirstName(_ firstName: String, andLastName lastName: String, fromAddress: String)
Note that in this example, the first parameter has an Internal name only, the second parameter has both and the last one only has one. The function call would look like
myFunctionToPrintDetailsOfStudentWithFirstName("John", andLastName: "Doe", fromAddress: "My Country")
As you can see, the first parameter is passed without a parameter name, the second parameter is passed using the External name and the last parameter is passed using the only parameter name. This makes the function call more readable.
Note:
Within the function declaration, the first parameter would be accessed by firstName, the second by lastName and the last one by fromAddress
Hope this clarifies the differences for you
This question is similar to
Swift 4 custom argument labels - required?
but more specific. I came across that question when researching a problem caused by changing from a var (requiring no parameter) to a func (requiring a parameter) but missed changing all references. I have created a playground that contradicts the claim made in a subsequent edit to that question: "question is incorrect, as custom labels are mandatory"
My question is: how to correctly express what I observed, as demonstrated below:
class SomeTest {
static func someParam(p1: String?) -> String? {
return "hello \(p1 ?? "nothing")"
}
// Uncommenting the following causes error at let funny
// static func someParam(p2: String?) -> String? {
// return "hello \(p2 ?? "nothing")"
// }
static func doIt() {
let funny = someParam // ignoring the argument label is ok if there is no ambiguity
funny("thing") // and can be used without
someParam(p1: "thing2") // must have argument label
}
}
SomeTest.doIt()
If you have both someParam functions (each with a differently named parameter), then the line:
let funny = someParam
no longer works since it isn't known which of the two someParam functions you are referring to. This is solved by providing an unambiguous name:
let funny = someParam(p1:) // or someParam(p2:)
Note that funny has a type of (String?) -> String?. Both someParam functions have that same type. This is why you need to provide more detail to disambiguate the two. The parameter names don't change the function type.
When directly calling a function you must provide the full function name which includes any named parameter labels.
But when you create a closure variable and assign it the value of a function, you don't need to provide more than the base name of the function if that name is unambiguous in the given context.
I have just started reading Learn Essentials of Swift
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
syntax to call
greet("Anna",day : "Tuesday")
My Questions:
What is the real need of sending the name of the parameter
Will it match the name before copying the value in the function
If it matches the names , if i interchange values while i call the function , below code fails
func greet(name: String, day: String,time: String) -> String
{
return "Hello \(name), today is \(day), \(time)."
}
greet("Anna", time: "one forty",day: "Tuesday")
How does the function parameter mechanism work internally ?
As you find in the link in the comment, there are some advantages of named parameters: They make the code clearer.
However, in Objective-C there has been named parameters from the very beginning. To be more honest, they have been akin of named parameters, because the names are part of the method name (selector). In your example, the method in Objective-C would be: greetName:day:. This is different from greetName:day:time:. At least Swift needs the capability to handle that.
What is the real need of sending the name of the parameter
Names parameters make the code more readable. There can be many methods with different parameter names.
Will it match the name before copying the value in the function
Yes. It builds the function name from the argument names in the call and try to match it with the parameter names of a potential method.
If it matches the names , if i interchange values while i call the function , below code fails
In Objective-C and Swift the order of the named parameters is important. You can have two different methods with interchanged names. greetName:day:time: is different to greetName:time:day:.
I am learning swift using learnxinyminutes.com
I'm having a hard time understanding a component of on of the examples on the site (below), namely the use of underscore in the let statements instead of variable names.
// Variadic Args
func setup(numbers: Int...) {
let _ = numbers[0]
let _ = numbers.count
}
I understand that swift wants you to use underscore if you never declare the variable, but 1) why would you want to declare variables you never use? And 2) is there a way to get those values out if you used _. And, 3) if so, how?
1) why would you want to declare variables you never use?
Generally you don't! There are some cases though where you might want to, such as the example Danny Buonocore gave. Another example might be this: say you want to check that a variable is non-nil before you do something, though you do not need that variable for the subsequent code. (A guard statement is probably more useful in these situations).
if let _ = titleString {
// Do something that doesn't use titleString, but where it being non-nil means this operation is valid
}
Another example is with Swift functions. Names for a second, third, etc. parameter must be identified whenever calling a function. For example:
func externalizedParameters(first: Int?, second: Int?) {
...
}
Which is called using externalizedParameters(5, second: 6).
But if you are doing something trivial, and the function name already makes it clear what the two parameters are, such as with a swap operation, you might not want to force the caller to explicitly state the name of the second parameter. In that case, you can use '_' because you don't care about the name of that externalized parameter:
func swap(first: Int?, _ second: Int?) {
...
}
This can then be called as swap(5, 6) as opposed to swap(5, second: 6).
2) is there a way to get those values out if you used _. & 3) if so, how?
No. You need to name the variable if you want to use the value.
One example would be a loop where you don't necessarily need the index.
for _ in 0..<10 {
}
In swift you can also externalize the names of the parameters. This allows the caller to pass by name, rather than order:
func myFunction(param1:String, param2:String) {
}
myFunction(param2: "second value", param1: "first value");
If you don't want to externalize the name of a parameter, you can include an underscore before it, like so:
func myFunction(param1:String, _ param2:String) {
}
In this case, you must pass the value to set param2 to as the second argument, and you cannot use the naming scheme seen in the first example.
If you need to use the value inside of a variable, declare it with a name and not _. The underscore says, I know this call returns a value but we're not going to use it, so it doesn't need a name. Swift emits warnings for unused function call results, so this is a way to suppress that warning.
I have seen code like this:
func hello(name: String, #helloMessage: String) -> String {
return "\(helloMessage), \(name)."
}
My question is what # mark means before parameter's name? Is that meaning that the parameter has to be specified when calling a function?
Moreover can anyone show me a difference with the function without this # mark? Code examples are more than welcome.
Update (Swift 3.*...)
the default behavior of the first parameter’s signature was changed drastically. To understand how argument labels (ex. “external parameters”) and parameter names (ex. “local parameters”) work, please read the chapter “Function Argument Labels and Parameter Names” from the Apple’s Swift-book.
Some examples:
func someFunction(parameterName: Int) { parameterName }
someFunction(parameterName: 5) // argument label not specified
func someFunction(argumentLabel parameterName: Int) { parameterName }
someFunction(argumentLabel: 5) // argument label specified
func someFunction(_ parameterName: Int) { parameterName }
someFunction(5) // argument label omitted
There is no difference in this behavior between methods and functions.
Update (Swift 2.*)
The feature described below was deprecated, one need to write the parameter name twice to get the same behavior as with hash symbol before.
Update (examples)
For functions: when the function is called and purpose of some parameters is unclear, you provide external names for those parameters.
func someFunction(parameterName: Int) { parameterName }
someFunction(5) // What is the meaning of "5"?
func someFunction(externalParameterName parameterName: Int) { parameterName }
someFunction(externalParameterName: 5) // Now it's clear.
But if external and local names are the same, you just write a hash symbol before the parameter name.
func someFunction(#parameterName: Int) { parameterName }
// It's actually like:
// func someFunction(parameterName parameterName: Int) { parameterName }
someFunction(parameterName: 5)
For methods: by default first parameter name is only local (like by functions), but second and subsequent parameter names are both local and external (like as you write a hash symbol before the parameter name, this # is implicitly there):
class SomeClass {
func someMethodWith(firstParameter: Int, andSecondParameter: Int) { ... }
}
SomeClass().someMethodWith(5, andSecondParameter: 10)
You can use # (or add an explicit external name) for the first parameter of the method too, but it'll not match Objective-C-style calling.
class SomeClass {
func someMethodWith(#firstParameter: Int, andSecondParameter: Int) { ... }
}
SomeClass().someMethodWith(firstParameter: 5, andSecondParameter: 10)
Original answer
If you want to provide an external parameter name for a function
parameter, and the local parameter name is already an appropriate name
to use, you do not need to write the same name twice for that
parameter. Instead, write the name once, and prefix the name with a
hash symbol (#). This tells Swift to use that name as both the local
parameter name and the external parameter name.
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itunes.apple.com/ru/book/swift-programming-language/id881256329?l=en&mt=11
This has changed in Swift 2:
now you specify an external parameter name before the internal one, instead of using # to force the existing name.
According to the convention, the method name contains the action verb and the first parameter is not specified when calling the method:
func sayHiFrom(sender: String, to: String) {
print("Hi from \(sender) to \(to)!")
}
sayHiFrom("Jules", to: "Jim")
Specifying an internal parameter name
This time the second parameter has a different name for using inside the method, without changing the external name. When there is two names for a parameter, the first one is external and the second one is internal:
func sayHiFrom(sender: String, to receiver: String) {
print("Hi from \(sender) to \(receiver)!")
}
sayHiFrom("Jane", to: "John")
Forcing an external parameter name
You can force the first parameter to have an external name:
func sayHi(from sender: String, to receiver: String) {
print("Hi from \(sender) to \(receiver)!")
}
sayHi(from: "Joe", to: "Jack")
In this case, it's better that the method name does not contain the action term, because the forced parameter name already plays its role.
Forcing no external parameter names
You can also remove the parameter name for other parameters by preceding them with _ (underscore):
func sayHi(sender: String, _ receiver: String) {
print("Hi from \(sender) to \(receiver)!")
}
sayHi("Janice", "James")
**
Shorthand External Parameter Names
**
If you want to provide an external parameter name for a function parameter, and the local parameter name is already an appropriate name to use, you do not need to write the same name twice for that parameter. Instead, write the name once, and prefix the name with a hash symbol (#). This tells Swift to use that name as both the local parameter name and the external parameter name.
This example defines a function called containsCharacter, which defines external parameter names for both of its parameters by placing a hash symbol before their local parameter names:
func containsCharacter(#string: String, #characterToFind: Character) -> Bool {
for character in string {
if character == characterToFind {
return true
}
}
return false
}
This function’s choice of parameter names makes for a clear, readable function body, while also enabling the function to be called without ambiguity:
let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v")
// containsAVee equals true, because "aardvark" contains a "v”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks.
https://itun.es/in/jEUH0.l
With previous versions of Swift everything what #ovejka posted was true. In Swift 2.0 and above it looks like # is unused (in this or similar context, not counting #available)
I agree. It is confusing, but I hope this helps clear it up.
If you don't use #, you can enter parameters without using their names, as long as they are in order:
func x(a:Int, b:Int, c:Int) {some code}
x(10,20,30) or x(a:10, b:20, c:30) //Still have to be in order!
...but if you add #, the first variant is not allowed, i.e. x(10,20,30), as Swift now forces labels to be used. You can only use x(a:10, b:20, c:30).
Why would that be? Clarity. Makes code more readable.