Wenderlich Questions Flashcards

1
Q

Consider the following:
var optional1: String? = nil
var optional2: String? = .None
What’s the difference between nil and .None? How do the optional1 and optional2 variables differ?

A
There is no difference. Optional.None (.None for short) is the correct way of initializing an optional variable lacking a value, whereas nil is just syntactic sugar for .None.
In fact, this statement outputs true:
nil == .None // On Swift 1.x this doesn't compile. You need Optional.None
Remember that under the hood an optional is an enumeration:
enum Optional {
  case None
  case Some(T)
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q
Here’s a global function that counts the number of unique values in an array:
func countUniques(array: Array) -> Int {
  let sorted = array.sort(
A
In Swift 2.0, generic types can be extended with conditions by enforcing type constraints. If the generic type doesn't satisfy the constraint, the extension is neither visible nor accessible.
So the global countUniques function can be rewritten as an Array extension:
extension Array where Element: Comparable {
  func countUniques() -> Int {
    let sorted = sort(
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Here’s a function to calculate divisions given to two (optional) doubles. There are three preconditions to verify before performing the actual division:
The dividend must contain a non nil value
The divisor must contain a non nil value
The divisor must not be zero
func divide(dividend: Double?, by divisor: Double?) -> Double? {
if dividend == .None {
return .None
}

if divisor == .None {
return .None
}

if divisor == 0 {
return .None
}

return dividend! / divisor!
}
This code works as expected but has two issues:
The preconditions could take advantage of the guard statement
It uses forced unwrapping
Improve this function using the guard statement and avoid the usage of forced unwrapping.

A
The new guard statement introduced in Swift 2.0 provides an exit path if a condition is not met. It's very helpful to check preconditions, because it lets you express them in a clear way -- without the typical pyramid of doom of nested if statements. Here is an example:
guard dividend != .None else { return .None }
It can also be used for optional binding, making the unwrapped variable accessible after the guard statement:
guard let dividend = dividend else { return .None }
So the divide function can be rewritten as:
func divide(dividend: Double?, by divisor: Double?) -> Double? {
  guard let dividend = dividend else { return .None }
  guard let divisor = divisor else { return .None }
  guard divisor != 0 else { return .None }
  return dividend / divisor
}
Notice the absence of the implicitly unwrapped operators on the last line, because both dividend and divisor have been unwrapped and stored in non-optional immutables.
One more thing. You can group guard statements, so you can make the function simpler:
func divide(dividend: Double?, by divisor: Double?) -> Double? {
  guard let dividend = dividend, divisor = divisor where divisor != 0 else { return .None }
  return dividend / divisor
}
There are now only two guard statements, because you specify the non-zero condition using the where clause on the unwrapped variable divisor.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Consider the following code that defines Pizza as a struct and Pizzeria as a protocol, with an extension that includes a default implementation for the method makeMargherita():
struct Pizza {
let ingredients: [String]
}

protocol Pizzeria {
  func makePizza(ingredients: [String]) -> Pizza
  func makeMargherita() -> Pizza
}
extension Pizzeria {
  func makeMargherita() -> Pizza {
    return makePizza(["tomato", "mozzarella"])
  }
}
You'll now define the restaurant Lombardi’s as follows:
struct Lombardis: Pizzeria {
  func makePizza(ingredients: [String]) -> Pizza {
    return Pizza(ingredients: ingredients)
  }
  func makeMargherita() -> Pizza {
    return makePizza(["tomato", "basil", "mozzarella"])
  }
}
The following code creates two instances of Lombardi's. Which of the two will make a margherita with basil?
let lombardis1: Pizzeria = Lombardis()
let lombardis2: Lombardis = Lombardis()

lombardis1. makeMargherita()
lombardis2. makeMargherita()

A
They both do. The Pizzeria protocol declares the makeMargherita() method and provides a default implementation. The method is overridden in the Lombardis implementation. Since the method is declared in the protocol in both cases, the correct implementation is invoked at runtime.
What if the protocol doesn't declare the makeMargherita() method but the extension still provides a default implementation like this?
protocol Pizzeria {
  func makePizza(ingredients: [String]) -> Pizza
}
extension Pizzeria {
  func makeMargherita() -> Pizza {
    return makePizza(["tomato", "mozzarella"])
  }
}
In this case, only lombardis2 would make the pizza with basil, whereas lombardis1 would make a pizza without it, because it would use the method defined in the extension.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

The following code has a compile time error. Can you spot where and why it happens?
struct Kitten {
}

func showKitten(kitten: Kitten?) {
  guard let k = kitten else {
    print("There is no kitten")
  }

print(k)
}
Hint: There are three ways to fix it.

A
The else body of any guard requires an exit path, either by using return, by throwing an exception or by calling a @noreturn. The easiest solution is to add a return statement.
func showKitten(kitten: Kitten?) {
  guard let k = kitten else {
    print("There is no kitten")
    return
  }
  print(k)
}
Here's a version that throws an exception.
enum KittenError: ErrorType {
  case NoKitten
}

struct Kitten {
}

func showKitten(kitten: Kitten?) throws {
  guard let k = kitten else {
    print("There is no kitten")
    throw KittenError.NoKitten
  }
  print(k)
}
try showKitten(nil)
Finally, here's an implementation calling fatalError(), which is a @noreturn function.
struct Kitten {
}
func showKitten(kitten: Kitten?) {
  guard let k = kitten else {
    print("There is no kitten")
    fatalError()
  }
  print(k)
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q
Swift 2.0 features a new keyword to make recursive enumerations. Here is an example of such an enumeration with a Node case that takes two associated value types, T and List:
enum List {
    case Node(T, List)
}
What's that keyword?
A

It’s the indirect keyword that allows for recursive enumeration cases like this:
enum List {
indirect case Cons(T, List)
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly