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.
Related
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 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.
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.
In Swift the elements we manipulates all have types.
When we use theses types, we can add a '!', '?' or nothing to express their nullability.
What shall I call the '?' or '!' used to express this trait ?
A type decorator ? A decorator ? Operator ? Something else ?
What shall I call the type created when using this character ?
Is it a new type ? Is it a decorated type ? A type variation ?
The swift compiler, seems to consider them as new types, However my question is not implementation or language dependent and therefor I tagged it as language agnostic.
Edit: I'm looking for a language agnostic name. I understand with pranjalsatija's comment optionals are defined as compound type.
However, this is a language implementation detail.
I could rephrase my questions as:
What do you call a character with a special meaning when used it a type definition, and how to call the derived type.
This term should probably apply to capital casing constants in ruby as the concept is similar.
? on the end of the type isn’t a decorator or operator. It’s hardcoded syntactic sugar in Swift that allows you to shorten Optional<Thing> to Thing?.
The ? doesn’t really have a name (at least I’ve never heard anyone on the Swift team use one), in the language reference it’s just described as “the postfix ?”. The language grammar doesn’t put it in a syntactic category.
Similarly, [Thing] is shorthand for Array<Thing>, but there isn’t a name for the square brackets in this context.
Describing Option<Int> as “derived from” Int would be to misuse the term “derived”. You can if you want describe it as “Optional specialized for Int”.
In fact you may be looking for the language-agnostic term for how Swift allows you to build types (like Optional<T> or Array<T>) that apply to any kind of type T without having to care what T actually is. In which case the term would probably be generics.
! is a little different. When applied to a type name as in Thing!, it’s shorthand for ImplicitlyUnwrappedOptional<Thing>, in the same manner as ?.
! when applied to a variable of type Thing? is equivalent to a postfix operator that tests the optional and if it is nil, terminates your program, something like this:
postfix operator !<T>(value: T?) -> T {
if let unwrapped = value {
return unwrapped
}
else {
fatalError("unexpectedly found nil while unwrapping an Optional value")
}
}
so in this context, ! can be described as an operator. But not in the first context.
For the terminology a given language uses to describe optionals, see the Option type wikipedia page.
Optionals in Swift technically are completely different types, not variations of the same type. However, to a developer, they seem to be variations, so we'll treat them as such. The ? and the ! don't really have a set, specified name just yet, at least not that I know of. In a sense, you shouldn't be calling them type decorators, because optionals are really new types on their own. So to answer your question, the ? and the ! are parts of a type's name, more than anything else. And the new type created when using a ? or an ! is just that. A brand new type.
The type created using '?' is an Optional and '!' is an Implicitly Unwrapped Optional
I think the answer here may help you out, they refer to both as decorations
Here's a larger explanation about exclamation marks
And here's one for question marks
I'm beginning to teach myself swift and I'm going through examples of games at the moment. I've run across a line of code that I thought was peculiar
scene.scaleMode = .ResizeFill
In languages I'm used to (C / Java) the "." notation is used to reference some sort of structure/ object but I'm not exactly sure what this line of code does as there is no specified object explicitly before the "."
Information regarding clarification of this non-specified "." reference, or when/ how it can be used, would be great
P.S. I'm using sprite kit in Xcode
In Swift, as in the other languages you mentioned, '.' is a member access operator. The syntax you are referring to is a piece of shorthand that Swift allows because it is a type-safe language.
The compiler recognises that the property you are assigning to is of type SKSceneScaleMode and so the value you are assigning must be one of that type's enumerated values - so the enumeration name can be omitted.
To add to PaulW11's answer, what's happening here is only valid syntax for enums, and won't work with any other type (class, struct, method, function). Swift knows the type of the property that you are assigning to is an enum of type SKSceneScaleMode, so lets you refer to the enum member without having to explicitly give the type of the enum (ie SKSceneScaleMode.ResizeFill).
There are some situations where there will be ambiguity, and you will have to give the full name, this will be dependant on the context. For example, you may have two different enum types in scope, that both have a matching member name.
EDIT
Updating this answers as I incorrectly specified this was only applicable to enums, which is not true. There is a good blog post here which explains in more detail
http://ericasadun.com/2015/04/21/swift-occams-code-razor/