Changes in terminology for Swift function parameter labels - swift

Swift provides the ability to give both an internal and external name/label for parameters of functions. But lately Apple seems to have resorted to only saying "Argument" and "Parameter" names/labels and dropped the use of internal/external to describe these things.
In the Swift documents, and WWDC videos, there are a few unclear efforts to describe the difference between a function's parameters and arguments, without referring to these as the outward facing or internal, such as:
Each function parameter has both an argument label and a parameter
name. The argument label is used when calling the function; each
argument is written in the function call with its argument label
before it. The parameter name is used in the implementation of the
function. By default, parameters use their parameter name as their
argument label.
Imagine a jump() function.
Internally, the names of "when" and "height" might be different, and these are the internal names. External and internal don't seem to be at all confusing, other than the ordering in the Function Definition and then Declaration:
func jump(_ who: String, whenToJump when: Float, howHigh height: Int){
// wait for whenToJump
// adjust who.y by howHigh
)
Which of these is a parameter, in the sense Apple is referring to them, and which is an argument?

Everything is described in detail in the section
Function Argument Labels and Parameter Names
in The Swift Programming Language (Swift 3)
Briefly, the differences between Swift 2 and Swift 3 are
"External name" (Swift 2) is now "Function Argument Label" (Swift 3)
"Internal name" (Swift 2) is now "Parameter Name" (Swift 3)
In (Swift 2) the first parameter is _ name (internal, but no external) by default
In (Swift 3) the first parameter is name name (function argument label and parameter name) by default.

Related

swift argument labels and keywords

I am trying to learn Swift and came across the argument labels and an online example as follows:
func setAge(for person: String, to value: Int) {
print("\(person) is now \(value)")
}
This can be then called as:
setAge(for: "Paul", to: 40)
My question is that isn't for a Swift keyword? I am wondering whether this use of for has some hidden meaning that I am missing or just that these keywords can also be used as argument labels?
or just that these keywords can also be used as argument labels?
Exactly. This is introduced in SE-0001 Allow (most) keywords as argument labels. The motivation is that:
Sometimes, the most natural label for an argument coincides with a language keyword, such as in, repeat, or defer. Such keywords should be allowed as argument labels, allowing better expression of these interfaces.
Though in SE-0001 it is said that inout, var and let are not allowed to be argument labels (back then they are used to describe the mutability of the parameter). This restriction was later relaxed. Now, only inout is not allowed as an argument label, and you get a warning if you use var or let as an argument label.
Yes this keyword can also be used as argument label.
Swift gives you flexibility to use any keyword except inout as argument label as it increases readability.

Three dots in Swift init method

I was looking at some Apple Combine source code and saw a Publisher name MergeMany with an init method defined like this:
public init(_ upstream: Upstream...)
What are the three dots ... after the Upstream? The value of Upstream is just another publisher as defined in the Struct definition.
public struct MergeMany<Upstream> : Publisher where Upstream : Publisher {
The three dots mean that it is a variadic function and can take a list of Upstream. This is a function of the Swift Language and not the Combine Framework.
From Sergio Pietri's Blogpost:
Why should we use variadic functions? When you declare this type of function you are adding flexibility to the code. For example: the printf is probably the most notable function that uses this principle. The printf will take N amount of arguments and has many different parameters to format the output it will print.
And from the Swift documentation:
A variadic parameter accepts zero or more values of a specified type. You use a variadic parameter to specify that the parameter can be passed a varying number of input values when the function is called. Write variadic parameters by inserting three period characters (...) after the parameter’s type name.
The values passed to a variadic parameter are made available within the function’s body as an array of the appropriate type. For example, a variadic parameter with a name of numbers and a type of Double... is made available within the function’s body as a constant array called numbers of type [Double].

What is the meaning of the : in Swift function signatures and why is there no comma when it seems there should be one?

Here's an example of what I'm talking about: https://developer.apple.com/documentation/foundation/nsmutableorderedset/1410287-insert
The insert function is shown as insert(_:at:)
When it's actually used, the insert function looks more like:
namesArray.insert("John", at: 3)
There's no : after "John" (though I suppose it could be "John":String -- is that what it's there for?), and the , that actually needs to go there is not mentioned in the function signature in the documentation. Am I just supposed to know/assume that the comma goes there when I actually use it? Is this the case for all Swift functions?
Please note that this is not a question about the underscore, _ -- I understand why it's there and what it's for. I'm specifically asking about the reasons for including : and not including , in the function signature.
The convention, frequently seen in documentation, is a concise way of referring to a function, using only the function name and argument labels.
So consider this function declaration:
func insert(_ objects: [Any], at indexes: IndexSet)
This is
a method called insert;
the first parameter name is called objects, this parameter has no argument label (designated with the _) and has a type of [Any]; and
the second parameter name is indexes, its argument label is at and has a type of IndexSet.
So you call it like so:
insert(someObjects, at: someIndex)
When you call it, you don’t care what the parameter names that are used inside that function, but rather just what the argument labels are. So, the convention when referring to that method in documentation is to omit the parameter names and types and just use the function name and the argument labels, but no comma:
insert(_:at:)
Note, you’d never actually use this syntax in your code. This is just a documentation convention employed to distill long function declarations down to something more manageable and concise:
For more information about argument labels and parameter names, see Function Argument Labels and Parameter Names
A : in the function signature always means an input argument to the function. The function signature contains the argument label followed by a :. The _ means there's no argument label, in which case you can omit the : as well when supplying that specific input argument to the function call.
This is exactly what you see with the insert(_:at:) function. You supply two input arguments to it, "John" and 3, but it only needs an argument label for the second input argument, hence you only need one :. It's also important to note that at call time, you separate the input arguments using ,, not :.
Swift functions have a unique way of specifying the signature, which is a carry over pattern from Objective C. There are 3 parts to specifying each input argument to the function signature. The signature for the function you mentioned is as follows:
func insert(_ objects: [Any],
at indexes: IndexSet)
Let's look at the second argument first:
at indicates the argument label, which is how the caller specifies the parameter.
indexes indicates the function's parameter name to the object. This means that in the body of the function, whatever was passed as at: would be referred to as indexes.
IndexSet is the type of the argument.
Part 1 can be something besides a name, too:
if it is not specified, the argument name and parameter label are the same. For example, if the signature were func insert(objects: [Any], indexes: IndexSet), the function would be called as o.insert(objects: ['a','b'], at: [1,2]).
If it is an underscore (_), then the argument has no label for the caller. This allows the caller to use the simpler, intuitive call o.insert(['a','b'], at: [1,2]).
In a signature, the colon separates the name of a parameter from its value. Functions have this anatomy:
func functionName(label1 parameter1: Type1, label2 paramter2: Type2) -> ReturnType {
...
}
where labels are the names seen when calling the function and parameters are the names of the values as used in the body of the function. A label of _ removes the label from the parameter when calling it.
When calling a function, the colon simply separates parameter labels from the values passed to the function. Commas separate different parameters. A parameter with no label requires no colon. The following function would have no colons at all:
func myFunc(_ par1: Int, _ par2: String) {
print(par1, par2)
}
myFunc(3, "what") // 3 "what"

Why does Swift require both argument label and parameter name in function declaration?

Why does Swift require both argument label and parameter name in a function declaration? I'm learning Swift and thus far haven't seen a use for an argument label.
By default ,parameters use their parameter name as their argument label.
-The Swift Programming Language 4.0.3
The argument label is chosen from the point of view of the caller. The parameter name is chosen from the point of view of the implementer. Sometimes the same name is a good choice from both points of view, sometimes it isn't. Swift gives you the freedom to make good choices from both points of view.

"cannot call value of non-function type" error when attempting to call the max(_:_:) function

I'm trying to call the max function: max(x: T, y: T). However I keep getting the following error when I type max(2,3):
error: cannot call value of non-function type Int
var a = max(2, 3)
I am a beginner, and I have never encountered a function signature that uses a type "T". SO threads relating to using the max function call it in the manner I am (like max(2,3) ) so I am not sure where I am going wrong.
I am looking for an explanation on the "T" and how to call functions that support generic types and how to make the max function return 3 when comparing integers 2 and 3.
The problem (as you've confirmed in the comments) is that you have defined a variable named max, causing a naming conflict with the function max(_:_:).
The solution therefore is to either specify the Swift module namespace (as George suggested) in order to disambiguate the fact that you're referring to the max(_:_:) function:
Swift.max(2, 3)
Or, preferably, you should consider renaming your variable. I strongly suspect that there's a more descriptive name you could give it (remember, the Swift API Design Guidelines favours clarity over brevity).
Are you calling max within extension Int?
Try Swift.max(2, 3).