Swift

Getting Shwifty!

So I’ve been using Swift for a while now. I started back at the end of 2014 and for the first while I essentially treated it like Objective-C with different syntax.  While functional, its not FUNCTIONAL. What I mean is that functions are first class citizens in swift and the swift language itself is a functional language.  There are three great examples of this when working with arrays these are the filtermap, and reduce methods

filter

When dealing with arrays I’ve been in the habit of simply creating new arrays, iterating over my array to create my new array and moving on with my life.  For example, say I had an array of numbers and wanted to find all the numbers above a certain amount.  I might tackle this like so:

let numbers = (1...10)
var numsGT4 = [Int]()
for num in numbers {
    if num > 4 {
     numsGT10.append(num)
    }
}

//numsGT4: [5, 6, 7, 8, 9, 10]

One problem with this is that numsGT4 is declared as a var, even if I didn’t want it to be alterable after creation.  Swift has a great function called filter that not only fixes this, but also simplifies my code:

let numbers = (1...10)
let numsGT4 = numbers.filter { (num) -> Bool in return nun > 4 }

Or, in an even more simplified form:

let numsGT4 = numbers.filter{$0 > 4}

Easy peasy lemon squeezy!  But the great thing is that the filter method takes another method as input and constructs an array from the results of that method.  So while the above example is perhaps a bit simplistic, it works for anything, classes, structs, you name it!

map

But lets say, instead of filtering your list, you would like to perform some action on it.  Again, I used to create arrays and simply iterate through my array, altering the values as they came and stuffing them into another array. Functional swift comes to the rescue again with the map function! For our example lets take the numbers array above and simply double their value (multiply each by 2). My old (bad) way:

var numbersDoubled = [Int]()
for num in numbers {
    numbersDoubled.append(2 * num)
}
// numbersDoubled: [2,4,6,8,10,12,14,16,18,20]

Using map:

let numbersDoubled = numbers.map { (num) -> Int in
    return num * 2
}

More simply:

let numbersDoubled = numbers.map { $0 * 2}

Again, the map function takes another function as input! Neat!

reduce

Lets say we want to take our array and reduce it to one single value. For example lets take all the numbers in our array and sum them up.  Old way:

var sum = 0
for num in numbers{
    sum += num
}
// sum: 55

The functional (correct) way:

let sum = numbers.reduce(0) { (finalValue, num) -> Int in
    return finalValue + num
}

Reduce is a bit more tricky than the other two methods, so lets look at its signature:

func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result

so we pass in an initial value of type Result (in our case it is the Int value 0). Then the function takes in a function that itself has a signature of (Result, Element) throws -> Result.  In our case this becomes (Int, Int)->Int. and finally the reduce function itself returns they type Result (again, Int in our case). Not to bad. Also, understanding this means that if we use our head we can simply our code even more!

let sum = numbers.reduce(0){$0+$1}

Or, if we realize that the ‘+’ operator is actually a function with signature of (Int,Int)->Int, we can simplify further:

let sum = numbers.reduce(0,+)

 

 

Try it out! Its been great fun learning to do things more functionally!

 

 

Swift

Count Your Many Blessings!

The Basics

So, Enums may not be the coolest of features in any language, but I must say that they are pretty neat in Swift.  In most language they are a simple counting or listing device, used to create a set list of options.  In C, for example, enums are only integers.

In Swift, enum can be strings, characters, ints or any floating-point type! For example, I once was writing an app that utilized the Parse backend.  To aid with my backend integration I created enums for the tables, with the column names as the case values.

enum UserTableColumn:String{
    case name
    case username
    case flagged
    case reported
}

This was great since it kept a clear list of the columns that I could easily check if it was in sync with the database.  Furthermore, Parses API used a string value to access the column in the object returned from the DB (kind of like a dictionary) and so to get the users name I could utilize the rawValue instance variable inherent with all enums. This variable returns the base value of the enum, integers, floating point numbers, characters, and strings.  If the enum has a string type, then the enum name is the basic return value.  Thus I could access the name of a database user object like this:

dbUserObject.valueForKey(UserTableColumn.name.rawValue) as? String

Using these tools I was able to write a wrapper class around the DB Objects to provide a cleaner, clearer interface.

 

Flying First Class

In swift enums are first class types, meaning that you can do a lot of things usually only available to classes and such.  For example, you can extend an enum to give it computed values, and make them conform to protocols.  For example, say we wanted to create an enum for different mass types.  We could do so like this:

enum Volume:Double{
    case Teaspoon   = 1
    case Tablespoon = 3
    case Cup        = 48
    case Pint       = 96
    case Quart      = 192
    case Gallon     = 768
    case Liter      = 202.884136211
    case Milliliter = 0.202884136211
}

If you know your units conversions, you can see that the rawValue of every case is in terms of how many teaspoons are in one unit of the respected volume (e.g. 1 Tablespoon = 3 Teaspoons, so Volume.Tablespoon.rawValue = 3).

Now if we want to convert between any volume, the equation is pretty simple.  For example, to find how many Tablespoons 9 Teaspoons is, you would use the following equation:

var numTbs = 9 * Volume.Teaspoon.rawValue / Volume.Tablespoon.rawValue // 3

Thats great, but we can expand this.  Lets create a protocol:

protocol ConvertableUnit{
    var rawValue:Double{get}
    var baseValue:Self{get}
    func convert(amount:Double, to unit: Self)->Double
}

First notice several things:

  • var rawValue:Double{get} helps access the base value of each case, as well as ensuring that the value is a double.
  • var baseValue:Self{get} we’ll use this to return the base value for conversion.  In this case we’ll return Volume.Teaspoon
  • func convert(amount:Double, to unit:Self)->Double This is the function that will actually calculate the conversion.

Now that we’ve declared our protocol, lets make our enum conform to it:

enum Volume:Double, ConvertableUnit{
    case Teaspoon   = 1
    case Tablespoon = 3
    case Cup        = 48
    case Pint   	= 96
    case Quart      = 192
    case Gallon     = 768
    case Liter      = 202.884136211
    case Milliliter = 0.202884136211
    
    var baseValue: Volume{
        return .Teaspoon
    }
    
    func convert(amount:Double, to unit: Volume) -> Double {
        return amount * self.rawValue * self.baseValue.rawValue / unit.rawValue
    }
}

We can use this like this:

let numTeaspoonsInTablespoon = Volume.Teaspoon.convert(amount:4, to: Volume.Tablespoon)// return 1.3333333333

We can even clean our code up a bit by simply doing an extension to the enum and separating the enum from its protocol conformance:

enum Volume:Double{
    case Teaspoon   = 1
    case Tablespoon = 3
    case Cup        = 48
    case Pint   	= 96
    case Quart      = 192
    case Gallon     = 768
    case Liter      = 202.884136211
    case Milliliter = 0.202884136211
}

extension Volume:ConvertableUnit{
    var baseValue: Volume{
        return .Teaspoon
    }
    
    func convert(amount:Double, to unit: Volume) -> Double {
        return amount * self.rawValue * self.baseValue.rawValue / unit.rawValue
    }
}