This one was all about closures
How to create and use closures
Passing function by reference
func greetUser() { print("Hi there!") } greetUser() // or get a copy var greetCopy = greetUser greetCopy()
Assign function directly to a variable
let sayHello = { print("Hi there!") } sayHello()
How to write a closure.
let sayHello = { (name:String) -> String in "Hi \(name)!" }
Note
– we don’t use parameter names when calling a closure
func greetUser() { print("Hi there!") } greetUser() // rewritten var greetCopy: () -> Void = greetUser greetCopy()
Scored 12/12 on Creating basic closures
Scored 7/12 on Accepting Parameters in a closure
Scored 10/12 on Returning Values from a closure
How to use trailing closures and shorthand syntax
Note: Just drop the argument types, and the return type
// You can also remove more clutter by getting rid of the // closure's parameter name and the () around it // So this: let sorted = t.sorted(be: { a, b in if a == "Suzanne" { return true } else if b == "Suzanne" { return false } return a < b }) // Turns to: let sorted = t.sorted { a, b in if a == "Suzanne" { return true } else if b == "Suzanne" { return false } return a < b }
Swift automatically provides parameter names for us, using shorthand syntax.
// So this: let sorted = t.sorted { a, b in if a == "Suzanne" { return true } else if b == "Suzanne" { return false } return a < b } // Turns to: let sorted = t.sorted { if $0 == "Suzanne" { return true } else if $1 == "Suzanne" { return false } return $0 < $1 }
Everything in the parameters is part of the function body.
The reverse sort example provided is simpler (meaning no branching as in the previous examples) and shows how the function could be made even more concise.
// Starting with: let reverseSort = t.sorted { return $0 > $1 } // can remove the return let reverseSort = t.sorted { $0 > $1 } let reverseSort = t.sorted { $0 > $1 }
When its best to not do it:
- The closure’s code is too long
- the provided parameters
$0
are used more than once - You have 3 or more parameters
More examples
let tOnly = t.filter { $0.hasPrefix("T") } let mappedVals = t.map { $0.uppercased() }
Scored 6/6 on Shorthand parameter names
How to accept functions as parameters
// Example func ma(size: Int, using generator: () -> Int) -> [Int] { var numbers = [Int]() for _ in 0..<size { // use the passed in function to generate an integer let newNum = generator() numbers.append(newNum) } return numbers } // Another func genNewNum() -> Int { Int.random(in: 1...20) } let newRolls = ma(size: 50, using: genNewNum)
Functions can accept multiple functions as parameters.
We can do this:
func doImpWork(first: () -> Void, second: () -> Void, third: () -> Void) -> Void { // doing the first thing first() // doing the second thing second() // doing the third thing third() }
or we can do this:
doImpWork { // first thing gets done } second: { // second thing gets done } third: { // third thing gets done }
Scored 11/12 on Closures as parameters.
Scored 11/12 on Trailing closure syntax.
Summary
- You can copy functions, the copy loses its parameter name
- All functions have types, their parameters have types and their returns have a type.
- A closure can be assigned to a variable or a constant
- Closure parameters are inside the function body followed by the word
in
- Functions can accept functions as parameters
- You can pass a dedicated function or a closure
- You don’t need to write the types of the parameters if Swift can figure it out
- If one or more parameters of a function are functions, you can use trailing closure syntax.
- Shorthand parameters like
$0
and$1
work but mainly under conditions - Its more important to know how to use this than how to create it