Reputation: 7741
When I cmd click the split function in Xcode, it takes me to the header file. This is what it reads
public func split(maxSplit: Int = default, allowEmptySlices: Bool = default, @noescape isSeparator: (Self.Generator.Element) throws -> Bool) rethrows -> [Self.SubSequence]
How does the following implementation work with above declaration?
someString.characters.split { $0 == "." }
Upvotes: 9
Views: 336
Reputation: 13316
Let's break it down:
public func split(maxSplit: Int = default, allowEmptySlices: Bool = default, @noescape isSeparator: (Self.Generator.Element) throws -> Bool) rethrows -> [Self.SubSequence]
maxSplit
: The first parameter, maxSplit
, allows you to specify the maximum number of pieces that the sequence will be split into. The default is Int.max
.
allowEmptySlices
: The second parameter, allowEmptySlices
specifies whether or not two consecutive separators in the sequence should lead to an empty slice. The default is false
. For example if you had a String, "A..B"
, and you split on the .
character, you could end up with either two (["A", "B"]
) or three (["A", "", "B"]
) items in the output array depending on what you pass for this parameter.
isSeparator
: The last parameter is the closure that you pass to identify where to split the sequence.
Since both maxSplit
and allowEmptySlices
have default arguments, you don't need to include them in your function call unless you want to change them. The only parameter that you have to supply is the isSeparator
closure.
In your case, you called:
someString.characters.split { $0 == "."}
...which is the equivalent of:
someString.characters.split(maxSplit: Int.max, allowEmptySlices: false) { $0 == ".' }
You could also write your function call like this:
someString.characters.split(isSeparator: { $0 == "." })
The way that you have written it makes use of the "trailing closure" syntax. If a function takes a closure as it's final argument, you can move the closure outside the parentheses like this:
someString.characters.split() { $0 == "." }
And if the function takes only one argument (not counting any default arguments that you are not supplying) then you can omit the parentheses altogether:
someString.characters.split { $0 == "." }
At the highest level, what happens is that split
iterates through the sequence of characters. It tests each character using the supplied closure, and if the closure returns true
, it splits the sequence on that character. In your case it will split the sequence of characters every time it locates a "."
.
Some other notes:
rethrows
: The whole function is marked rethrows
. It will throw an error, but only if the closure that you pass for the isSeparator
argument throws an error itself. Note that the isSeparator
parameter allows you to pass a closure that throws an error, but you don't have to. Any time a function accepts a closure that throws an error, it will also accept a closure that does not throw. This is because non-throwing functions are a sub-type of throwing functions.
@noescape
: The isSeparator
parameter is marked @noescape
. That simply means that nothing in the closure will survive past the end of the call to split
.
Upvotes: 5
Reputation: 32924
someString.characters.split { $0 == "."}
is equivalent to
someString.characters.split(isSeparator: { $0 == "."})
the closure in your code is called a trailing closure, closures that are the last parameter to a function can be placed after the function declaration, and if no other parameters remain, you can also omit ()
.
The first two parameters have default values, so they can be omitted, leading to the simplified call you posted.
Upvotes: 2
Reputation: 57184
Your line someString.characters.split { $0 == "."}
uses the default values for maxSplit
and allowEmptySlices
and specifies a custom closure for isSeparator
. Some longer version of calling the function split
is:
let arr = str.characters.split(Int.max, allowEmptySlices: false) { (char) -> Bool in
char == "."
}
Since the above code uses the same values as the actual defaults (Int.max
and false
) you can remove the first two parameters and since the closure is the last parameter (making it a trailing closure) you can omit the entire parameter and simply write a closure in the following way:
let arr = str.characters.split { (char) -> Bool in
char == "."
}
Now we can simplify the closure by omitting the specific signature:
let arr = str.characters.split { $0 == "." }
Upvotes: 5