Why can I call Array.max this way? [duplicate] - swift

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.

Related

What is the keyword repeating used for in Swift? [duplicate]

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.

What does 'using' do in Swift methods? [duplicate]

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.

Confused by the example code which adds new instance methods to types

The following code snippet is copied from the official document where it is used to demonstrate how to use the Extensions to add method to existing types.
extension Int {
func repetitions(task: () -> Void) {
for _ in 0..<self {
task()//what's going on here?
}
}
}
3.repetitions { //why I don't have to call as `repetitions()`
print("Hello!")
}
Question: The question is not asking how the extinsion extens. I just feel a bit confused about this code, why it looks like so? why use task() inside function body? Where it comes from? for the line 3.repetition why not write it as 3.repetition()
Thanks a lot
repetitions is a function that accepts as its parameter a function and calls that function several times.
To call repetitions, we could say (note, this is Swift 3):
func sayHi() {
print("Hello")
}
3.repetitions(task:sayHi)
But why define an extra name sayHi? Instead we use an anonymous function:
3.repetitions(task:{print("Hello"})
But in that case we are allowed to omit the parenthesis in this call to repetitions and use trailing syntax:
3.repetitions{print("Hello")}
Why use task() inside function body?
The task parameter is defined as a closure aka an anonymous function:
task: () -> Void
This says that the function expects another function as a parameter, one which takes no arguments and returns no values.
Calling task() invokes that function which is passed in.
for the line 3.repetition why not write it as 3.repetition()
Search for "Trailing Closure Syntax". If the last argument to a Swift function is a closure, you can attach it to the call outside of the () argument list.
Or in other words, this is exactly the same:
3.repetitions(task: {
print("Hello!")
})
(whether you have to use task: as the keyword argument depends on whether you use Swift 2 or 3.

Swift 3 first parameter names

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.

Swift: A function as an another functions argument

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).