This question already has answers here:
What is the point of having two different names for the same parameter?
(3 answers)
What are the new "for", "at", "in" keywords in Swift3 function declarations?
(1 answer)
Closed 4 years ago.
I am reading the official "The Swift Programming Language (Swift 4.2)" book and in the part Swift Tour/Generics I encounter the following code
func makeArray1<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
var result = [Item]()
for _ in 0..<numberOfTimes {
result.append(item)
}
return result
}
let arr1 = makeArray1(repeating: "knock", numberOfTimes: 4)
print(arr1)
which prints out
["knock", "knock", "knock", "knock"]
I am confused with the role of the word 'repeating' in the definition of the function makeArray1. I tried to run the code without that word with the following code
func makeArray2<Item>(item: Item, numberOfTimes: Int) -> [Item] {
var result = [Item]()
for _ in 0..<numberOfTimes {
result.append(item)
}
return result
}
let arr2 = makeArray2(item:"knock", numberOfTimes:4)
print (arr2)
and the code gave the same result as before.
["knock", "knock", "knock", "knock"]
So what is the use of 'repeating' in the code?
It's not a keyword, it's an optional function argument label that can differ from the local parameter name that's used inside the function/method.
Read the section Function Argument Labels and Parameter Names in The Swift Programming Language:
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. …
You write an argument label before the parameter name, separated by a space …
If you don’t want an argument label for a parameter, write an underscore (_) instead of an explicit argument label for that parameter.
Related
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.
This question already has answers here:
In Swift, what's the difference between calling UINavigationController() vs UINavigationController.init()?
(3 answers)
Closed 5 years ago.
class A {
private var value: Int
init(value: Int) {
self.value = value
}
}
We have class A and what is the difference between I create this object by using A.init(value: 5) and A(value: 5)? Thanks
There is no functional difference between the two. Both styles will call the same initializer and produce the same value.
Most style guides that I've seen prefer to leave out the explicit .init-part in favor of the shorter A(value:) syntax — that also resembles the constructor syntax in many other languages.
That said, there are some scenarios where it's useful to be able to explicitly reference the initializer. For example:
when the type can be inferred and the act of initialization is more important than the type being initialized. Being able to call return .init(/* ... */) rather than return SomeComplicatedType(/* ... */) or let array: [SomeComplicatedType] = [.init(/* ... */), .init(/* ... */)]
when passing the initializer to a higher order function, being able to pass "something".map(String.init) rather than "something".map({ String($0) })
Again, it's a matter of style.
This question already has an answer here:
What are the new "for", "at", "in" keywords in Swift3 function declarations?
(1 answer)
Closed 5 years ago.
I noticed that in I was getting an error unless I did
animateTransition(using transitionContext: UIViewControllerContextTransitioning)
However some tutorial present this method as,
animateTransition(transitionContext: UIViewControllerContextTransitioning) without the using.
It only seems to build if I include using but I'm curious as to it's role and when the change occurred.
check apple documentation
Specifying Argument Labels
You write an argument label before the parameter name, separated by a
space:
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
}
Here’s a variation of the greet(person:) function that takes a
person’s name and hometown and returns a greeting:
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// Prints "Hello Bill! Glad you could visit from Cupertino."
The use of argument labels can allow a function to be called in an
expressive, sentence-like manner, while still providing a function
body that is readable and clear in intent.
This question already has an answer here:
Parameters after opening bracket
(1 answer)
Closed 6 years ago.
I'm using Xcode 8.2.1. If I look at the documentation for Array I find this declaration for the max method:
public func max(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?
The argument label is by and the argument name is areInIncreasingOrder. Since the label is specified explicitly I thought it has to be included in a call to the function but the following code works if I omit the label (i.e by).
Am I misunderstanding how argument labels are used when calling a method? Or, is my example code calling a different version of the max method?
Example code:
let names = ["Talyor", "Paul", "Adele"]
let longest = names.max { $1.characters.count > $0.characters.count }
print(longest!) // "Taylor
When the last parameter of a method is a closure, you can write it in curly braces after the method call and omit the name of the parameter.
See the Trailing Closure documentation.
EDIT: I'm aware that I was using the wrong Xcode version for Swift 2, now. Problem solved.
I'm following the Swift 2 book from Apple. At a point there's the following example:
import Foundation
func hasAnyMatches(list: [Int], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, condition: lessThanTen)
What I think is weird is the last line. Why does it say condition: lessThanTen and not just lessThanTen? My compiler (Xcode) also gives me an error doing it the way it's shown in the book.
Also: why does it only say list: [Int] in the third line but condition: Int -> Bool? Why not something like list: [Int] -> Int?
Swift functions and methods can define their parameters to either have external names or not.
By default, the first parameter omits its external name, and the
second and subsequent parameters use their local name as their
external name.
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2 Prerelease).” iBooks. https://itun.es/us/k5SW7.l
The the tag condition: is the external name for the closure that you are passing to your hasAnyMatches function.
That code should compile and run.
My compiler (Xcode) also gives me an error doing it the way it's shown in the book.
Because the language has changed! In Swift 2, which you are reading about, the function has condition: so your call must have condition:. But you are testing in Swift 1.2, a very different language, where the rules are not the same.
In Swift 1.2, a top-level function declared with condition: means that your call should not have condition:. In Swift 1.2, to require the call to have condition:, the function declaration would have to say # condition:.
You are confusing yourself. Update Xcode so that the language you are using is the same as the language you are reading about.
It says condition: lessThanTen because in Swift you can define "labels", that is, descriptions for the data that a function call requires. It gives you an error because the call would be correct if the function declaration was func hasAnyMatches(list: [Int], #condition: Int -> Bool) -> Bool (at least this would be the case with Swift 1.2). The number sign produces, inside every call to the function, a label identical to the name of the function argument. Said label must not be deleted from the call, since it's there to clarify the purpose of that parameter to whoever invokes the function.
list: [Int] means that the first function argument takes name "list" and is of type [Int]. condition: Int -> Bool means that the second function argument takes name "condition" and is of type "Int to Bool", that is, condition is a function that takes a single argument of type Int and returns a value of type Bool. In fact, if you read the last line, in the call to the function hasAnyMatches the following are passed: i) an array of Ints and ii) a function that takes an Int and returns a Bool (note that when passing functions as parameters we only write their name - no parentheses).