McFlurry™

While working with RAC 3.0, I find myself in this situation a lot1:

aSignal.flatMapLatest { v in transformation(v) }  

Which can be simplified into:

aSignal.flatMapLatest(transformation)  

The problem is when our transformation, doesn't really fit what we need.

func fileCreationDate(fullPath: String) -> SignalProducer<NSDate, Error>  

So given a path to a file, it will return a SignalProducer with its creation date, or an error. The transformation I want to use is in this form:

func isDate(date: NSDate, laterThan minutes: NSTimeInterval) -> SignalProducer<Bool,Error>  

Which will tell me if the file was created N minutes ago. This is used for the caching purge mechanism. The entire flow will then look like this:

fileCreationDate(path).flatMapLatest { date in isDate(created:date, laterThan:5) }  

But I just want to pass the transformation that the flatMapLatest needs. The later will then provide its inner value to the transformation (in this case a NSDate). This brings me to the problem:

In one hand I want to preserve the signature of the method, because it conveys exactly what it does. But on the other, I want to bend it to my use case.

Enter McFlurry™: a flip + curry. We start by currying the function isDate. Signature wise, it will go from:

(NSDate, NSTimeStamp) -> SignalProducer<Bool,Error>

to:

NSDate -> NSTimeStamp -> SignalProducer<Bool,Error>

Now, I want to fix the minutes param 2, but I can't, because I need to first pass the NSDate (which I have yet to have):

curry(isDate)(???)(minutes)  

So I need to flip the params, so I can fix the minutes:

flip(curry(isDate)) // NSTimeStamp -> NSDate -> SignalProducer<Bool,Error>  

And then:

flip(curry(isDate))(5) // NSDate -> SignalProducer<Bool,Error>  

And finally I use it in the flatMapLatest:

let isDateOlderThan5Minutes = flip(curry(isDate))(5)

fileCreationDate(path).flatMapLatest(isDateOlderThan5Minutes)  

This might seem a bit convoluted, but when you have big flows, these techniques will improve your code readability.

  1. flatMapLatest is nothing more than a normal flatMap with .Latest already specified inside.

  2. This is called partial application