In that example, you aren't using filter
, sorted
and map
as parameters, you are calling those functions with closures as their parameters.
Here are those functions:
func filter(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> [Self.Element]
func sorted(by areInIncreasingOrder: (Self.Element, Self.Element) throws -> Bool) rethrows -> [Self.Element]
func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]
You can see that each one takes a closure expression as a parameter.
So when, for instance, you call .filter { $0 % 2 == 1 }
, the { $0 % 2 == 1 }
is the closure being passed in.
The reason you see .filter
, .sorted
and .map
with the leading .
is because these are three different functions being chained together onto luckyNumbers
. First you call filter
to get a filtered array from luckyNumbers
, then you call sorted
on that filtered array to get the array sorted in ascending order, then you call map
to convert the filtered and sorted integers into a String
. You are essentially feeding the result of one function into the input of another function.
In this way, you can chain multiple operations together without having to create intermediate variables to hold your results. The long way of doing it:
let filteredLuckyNumbers = luckyNumbers.filter { $0 % 2 == 1 }
let sortedLuckyNumbers = filteredLuckyNumbers.sorted { $0 < $1 }
let mappedLuckyNumbers = sortedLuckyNumbers.map { "\($0) is a lucky number"}
Can be shortened to:
let newLuckyNumbers = luckyNumbers.filter { $0 % 2 == 1 }
.sorted{ $0 < $1 }
.map { "\($0) is a lucky number"}
Both of these things—passing functions as parameters to other functions and chaining functions together—lie at the core of functional programming.