The Swift Programming Language Companion: Review of Basics to Functions (Part 2)
Tags: ios, swift, beginners
Published: 2020-02-02 17:37:54

This article is part of a series on learning Swift by writing code to _The Swift Programming Language_ book from Apple.

We've covered the basics up to functions, and reviewed them in the [last article](https://dev.to/loufranco/the-swift-programming-language-companion-review-of-basics-to-functions-359), and we're going to continue reviewing those chapters in this one.

### Set up a reading environment

If you are jumping around these articles, make sure you read the [Introduction](https://dev.to/loufranco/the-swift-programming-language-companion-introduction-4k0a) to see my recommendation for setting up a reading environment.

### Exercises

For this chapter, we're going to write code inspired by the Maps app.

Copy this into your playground

```
let places: [[String: Any]] = [
    ["name": "Buckingham Palace", "location": (lat: 51.5000632, long: -0.1449567)],
    ["name": "Great Pyramid of Giza", "location": (lat: 29.9792391, long: 31.1320079)],
    ["name": "Sydney Opera House", "location": (lat: -33.8567799, long: 151.2131027)],
    ["name": "Machu Picchu", "location": (lat: -13.163136, long: -72.5471569)],
    ["name": "Victoria Falls", "location": (lat: -17.9149133, long: 25.8379429)],
    ["name": "Empire State Building", "location": (lat: 40.7484445, long: -73.9878584)],
    ["name": "The Forbidden City", "location": (lat: 39.9394501, long: 116.1152174)],
    ["name": "Parthenon", "location": (lat: 38.3336346, long: 20.9712001)],
]
```

To make sure you understand how to access data in this structure, start with this code:

```
let name = places[0]["name"] as? String
let location = places[0]["location"] as? (lat: Double, long: Double)
location?.lat
```


In your Playground write code to do the following

1. Print out the longitude (`.long`) of The Sydney Opera House.
2. Use [this page to find the distance between two of these places](https://www.movable-type.co.uk/scripts/latlong.html) by plugging in their latitudes and longitudes.
3. Implement the Haversine distance formula. If you are an experienced programmer (just new to Swift), then read the Javascript version on that page and try to port it.
4. Once you have that, write a function that takes the `places` data and returns the two places that are closest to each other. (In Swift, the basic math functions are all global functions: `sin`, `cos`, `atan2`, `pow`, etc)

More help for beginners

Ok, step one is to declare a function that takes two lat/long tuples and returns a `Double`.

Start with this:

```
let location1 = places[0]["location"] as? (lat: Double, long:Double)
let location2 = places[1]["location"] as? (lat: Double, long:Double)

func distanceKm(loc1: (lat: Double, long: Double)?, loc2: (lat: Double, long: Double)?) 
-> Double? {
    if let loc1 = loc1, let loc2 = loc2 {
        // Implement Haversine here
        return 0 // .. replace this line
    }
    return 0
}

distanceKm(loc1: location1, loc2: location2)
```

Here is the basic algorithm:

1. Declare a constant `R` which is 6371000.0 (the radius of the Earth)
2. Declare a constant `phi1` which is `loc1.lat` in radians: `loc1.lat * .pi / 180.0` (in general: `radians = degrees * .pi / 180.0`)
3. Declare a constant `phi2` which is `loc2.lat` in radians
4. Declare a constant `deltaPhi` which is `(loc2.lat - loc1.lat)` in radians
5. Declare a constant `deltaLambda` which is `(loc2.long - loc1.long)` in radians
6. Declare a constant `a` to be `pow(sin(deltaPhi / 2), 2) + cos(phi1) * cos(phi2) * pow(sin(deltaLambda/2), 2)`
7. Declare a constant `c` to be `2 * atan2(sqrt(a), sqrt(1-a))`
8. Return `R * c / 1000.0`

`distanceKm(loc1: location1, loc2: location2)` should be around `3511` just like the web page.

Now see if you can find the two closest places. Start with this

```
func closestTo(places: [[String: Any]], loc: (lat: Double, long: Double)) -> String {
    var smallestDistance = Double.greatestFiniteMagnitude
    var closest = ""

    for p in places {
        if
            let name = p["name"] as? String,
            let loc2 = p["location"] as? (lat: Double, long: Double),
            let distance = distanceKm(loc1: loc, loc2: loc2),
            distance < smallestDistance {
                smallestDistance = distance
                closest = name
        }
    }

    return closest
}

// Find the closest place to the Eiffel Tower (should be Buckingham Palace)
closestTo(places: places, loc: (lat: 48.8583736, long: 2.2922873))
```

Use this function as a start. You need to make sure you don't compare a place to itself, because that will always be the closest.

DM me or comment below if you need help.

### Next: Closures

The next article will provide exercises for the [Closures](https://docs.swift.org/swift-book/LanguageGuide/Closures.html) chapter. Read it before you move on.