Programming in Swift · Structures | Ray Wenderlich

Hi guys,
In the extension for the Location struct, you added a computed variable that returns a bool.
I can see the code in the variable executes a ‘contains’ function on the ‘restaurants’ array and takes in a closure. So basically this closure looks like a bit of code I can customise to decide when I want ‘contains’ to return true or not. So our closure here is basing the result on the result of the restaurant.willDeliver function (which in turn takes in a Location as a variable, and so we’ve used ‘self’ because we want it to calculate it based on ‘this’ instance of a Location.
All fine there.
But how on earth were we able to make a reference to ‘restaurants’ and ‘restaurant’ inside the Location extension? A Location has properties and methods. At no point did we ever pass ‘in’ restaurants to the struct. How does a Location even know what a ‘restaurant’ is then? Doesn’t this fall foul of scope rules?

In this example, you can think of the playground page representing the scope of PizzaTown, in which the restaurants exist. All the code in the playground page has access to that parent scope of the town.

If it would be useful, you could instead make a struct or enum for the town itself, like this:

enum PizzaTown {
  static let restaurants = [
    Restaurant(location: Location(x: 0, y: 0), deliveryDistance: 3),
    Restaurant(location: Location(x: 5, y: 5), deliveryDistance: 2)
  ]
}

Extensions that go along with types like that are often useful within the scope of a single file. To restrict them from being used elsewhere, you can use the private keyword:

private extension Location {
  var canGetPizzaDelivery: Bool {
    return PizzaTown.restaurants.contains { restaurant in
      restaurant.willDeliver(to: self)
    }
  }
}

Alternatively, as you were suggesting, you can pass in the restaurants as an argument. When I convert from computed properties to functions, though, I append the prefix get**, and the resulting name is a little harder to parse than I wanted to introduce here! :smile_cat:

extension Location {
  func getCanGetPizzaDelivery(restaurants: [Restaurant]) -> Bool {
    return restaurants.contains { restaurant in
      restaurant.willDeliver(to: self)
    }
  }
}

** That’s because of being able to store methods in closures, and needing to disambiguate those closures from the results of calling them. Again, this video was overly complex enough without introducing that here!

let getCanGetPizzaDelivery: ([Restaurant]) -> Bool
  = Location(x: 3, y: 0).getCanGetPizzaDelivery

let canGetPizzaDelivery: Bool
  = getCanGetPizzaDelivery(restaurants)
1 Like

Ok I though closures & collections was confusing…
Why at 5 minutes in are you and your competing restaurant both defined
by the same name just different co-ordinates? can you have say restaurant & competingRestaurant. How do you know which is which ??

Hi!

It wasn’t really important which restaurant was which, in the array. We just needed to create a collection of them in order to define canGetPizzaDelivery later. Sorry we didn’t make that more clear!

Are you aware that the new version of this course is out? We tried to address a lot of the confusion people were having with collections and structures there!

https://www.raywenderlich.com/5539282-programming-in-swift-fundamentals

Thanks for the reply Jessy, My ocd kicking in there I’m too busy trying to visualise the other restaurant, will definitely be looking at the new material
Thanks
Andy

Me too I repeated the video 3 times to understand the concepts but still confused.

Please don’t watch this anymore. It’s old! We’ve incorporated everyone’s feedback into the two new Programming in Swift courses. Enjoy! https://www.raywenderlich.com/paths

1 Like

Thank you @jessycatterwaul for the explanation :grinning: