Swift Functions

Posted on Thu 13 February 2020 in swift

Onward to day 5 of 100 Days of Swift. Today was all about functions, and there were a few things that I didn't remember, mainly because I don't use them much when I code.

First up is variadic functions. I don't use these because I tend to use arrays when I need to pass in an arbitrary number of values of the same type. Because swift doesn't support splatting, you have to do this either as an array or with a variadic function, there's no way to safely do both at the same time without helper functions.

func todayISaw(_ taxa: String...) {
    if taxa.contains("California Slender Salamander") {
        print("Today was a good day!")
    } else {
        print("Better luck tomorrow.")
    }
}

Another thing I've mostly forgotten about with Swift is function parameter default values. I use this feature a lot in python to provide sensible defaults for training parameters, like the number of epochs to run or the number of validation batches per validation pass.

func hike(whileMakingObservations: Bool = true) {
    if whileMakingObservations {
        print("What a lovely day!")
    } else {
        print("Why not?")
    }
}

I also forgot about inout parameters, I guess it's a feature that I don't really use and that I tend to code around. I think the main place I see it in Objective-C is with error handling. While the tutorials all use inout to modify primitive values, that seems like a contrived example to me. Passing by reference, however, could be useful:

func makeObservation(taxon: String, lifeList: inout Set<String>) {
    print("Nice \(taxon) sighting!")
    lifeList.insert(taxon)
}

var lifeList = Set<String>()
makeObservation(taxon: "Toyon", lifeList: &lifeList)
makeObservation(taxon: "California Poppy", lifeList: &lifeList)

And one last thing that I didn't remember: using multiple catch blocks to handle different kinds of errors.

enum ObservationError: Error {
    case NoTaxon
    case NoDate
    case NoGPS
}

func makeObservationFromDict(_ dict: Dictionary<String, Any>) throws {
    guard dict["taxon"] != nil else { throw ObservationError.NoTaxon }
    guard dict["date"] != nil  else { throw ObservationError.NoDate }
    guard dict["gps"] != nil   else { throw ObservationError.NoGPS }

    // make observation...
}

var obsDict: [String: Any] = ["taxon": "Genus Scaphinotus", "date": Date()]
do {
    try makeObservationFromDict(obsDict)
} catch ObservationError.NoTaxon {
    print("Please tell us what you saw.")
} catch ObservationError.NoDate {
    print("Please tell us when you saw it.")
} catch ObservationError.NoGPS {
    print("Please tell us where you saw it.")
}

Today's annoyance: the iPad Playgrounds Swift runtime crashed when I was 90% done with the day's lesson. I had to reset (in app, I never closed the Playgrounds app), and it deleted the entire page of code. I'm now looking very suspiciously at this text/code editor which can delete my work without warning.