Optional methods in pure Swift protocols

Ash Furrows wrote a very interesting post on optional conformance to a contract, and described the challenge of wanting to have two classes talk to each other without being tightly coupled (it's well worth reading David Owens response too), but I wanted to jump in and just share a pattern I used for a completely different reason (and something which is likely to be the topic of another post, so I won't go into it here). 

One of the challenges Ash highlighted (can one blogger just call another by their first name without permission? I'll assume that's OK) is that to have optional parts of a protocol it must be an @objc protocol. The challenge Ash highlights is that this then means you can apply it to all of the Swift types (struct and enum, we are looking at you).  

Well that's not very Swift is it? There is a different (note I didn't say better, just different) solution. 

In his example he highlights an optional var, but the example below covers functions too. Here's a protocol that has an optional var and an optional function. I'm jumping through some hoops to support structs (which can't mutate self in a block)

protocol Food{
    var caloriesPerGram : Double {get}
    var milliLitresWaterPerGram : Double? {get}
    var addWater : ((milliLitres:Double)->(Food))? {get}
}

struct Kibble : Food{
    var caloriesPerGram : Double {
        return 1.0
    }
    
    var milliLitresWaterPerGram : Double? { return nil }

    var addWater : ((milliLitres:Double)->(Food))? { return nil }
}

struct Flakes : Food{
    var absorbedWater = 0.0
    
    var caloriesPerGram : Double {
        return 0.5
    }
    
    var milliLitresWaterPerGram : Double? {
        return absorbedWater
    }
    
    var addWater : ((milliLitres:Double)->(Food))? {
        return { (milliLitres:Double)->Food in
            Flakes(absorbedWater: self.absorbedWater+milliLitres)
        }
    }
}

class Powder : Food{
    var absorbedWater = 0.0
    
    var caloriesPerGram : Double {
        return 0.5
    }
    
    var milliLitresWaterPerGram : Double? {
        return absorbedWater
    }
    
    var addWater : ((milliLitres:Double)->(Food))? {
        return { [unowned self] (milliLitres:Double)->Food in
            self.absorbedWater += milliLitres
            
            return self
        }
    }
}

var myFlake : Food = Flakes()
myFlake = myFlake.addWater?(milliLitres: 10.0) ?? myFlake

var myPowder : Food = Powder()
myPowder = myPowder.addWater?(milliLitres: 15.0) ?? myPowder

As I'm jumping through hoops to support structs. In case it's not obvious (??) any optional chain has an optional result, so I must use ?? to provide a value to use if the chain did result in nil. Another disadvantage is that with optional you can just ignore the var or func entirely in the implementing Type. Not so here, I must create something that returns nil

If you ignored structs you could just call the block with an optional chaining, and there would be no need for any returned object in the block declaration

protocol Food{
  // as before, except 
  var addWater : ((milliLitres:Double)->())? {get}  
}

myPowder.addWater?(15.0)

But I agree with Ash, any Swift solution that does support all Types, isn't really Swift. This solution is more than a little anguished (at least for the method case, I'm OK with the the nil returning var to be honest), but surely they could coax the compiler into doing this bit for us? 

On Typed Tuples in Swift

Tuples are a wonderfully powerful thing... from iterating a dictionary getting both key and value

for (key,value) in myDictionary{
  println("My key is \(key) and it has a value of \(value)")
}

To returning richer data from functions

func getResponse()->(responseCode:Int,payload:String?){
  //
  // Do stuff
  //
  return (404,nil)
}

All the way to augmenting enums

enum ServerResposne{
  case Error(Int)
  case Success(String)
}
  
let response = ServerResponse.Error(404)

I have found them particularly useful when you don't want to define an entire new type (be it struct, enum or class), but do need to compose a couple of things together into a package (our second case, richer data from functions). However, like so many convinces they come at a cost when you think about future you. You are both dependant on nice meaningful variable names, and even though you can name the fields of the tuple, you can't provide a hint as to exactly what the tuple is intended to encapsulate. You don't get compiler type checking, and if you decide to replace them there is no way to easily identify everywhere that particular structure is used. 

Except of course there is a one line way to protect against all of these issues, just define the tuple as a type alias

typealias ServerResponse = (responseCode:Int,payload:String?)

That's it. Now if you decide you want to capture this in a stronger type you can just replace that alias with the desired type, and the compiler will pick out everything that needs updating as a result. If you are lucky, that may even just be fixing the places where the tuples were created and the rest will just fall out. 

So we have a rule, if a tuple leaves a function scope (or greater), it gets a typealias. It's been a wonderful way of avoiding unnecessary additional types, but allowing your code to grow into them if needed.