Inline Blocks as Result-Producing Helpers

In a recent post, I wasn’t too fond of inline helper functions.

func displayComplexComputation() {
    
    // Outer scope
    let x = numberOfBananas()
    
    func subComputation() -> Int {
        let y: Int = ...
        // Access in inner scope through capturing in this closure
        return x * (y + someOtherFactor)
    }
    
    let result = subComputation() + ...
    
    someView.showResult(result)
}

Similar things can be accomplished with blocks instead of functions, as both are closures that capture their contexts. Blocks don’t even have to have a name. Inner functions and blocks share the same semantics. Found in Little Bites of Cocoa #180:

enum Theme {
  case Day, Night, Dusk, Dawn

  func apply() {
    // ...

    let backgroundColor: UIColor = {
      switch self {
        case Day: return UIColor.whiteColor()
        case Night: return UIColor.darkGrayColor()
      }
    }()

    // ... set backgroundColor on all UI elements
  }
}

I love how lazy properties are handled in Swift. This is exactly the same approach. Bundling a sequence of set-up instructions into a closure helps readability, I find.

Take for example constructing and formatting a NSDate from NSDateComponents, which is always taking at least 4 lines of code:

let timeFormatter: NSDateFormatter = ...
let hour: UInt = ...

let timeOfDay: String = {
    let comps = NSDateComponents()
    comps.hour = hour

    let calendar = NSCalendar.currentCalendar)
    let date = calendar.dateFromComponents(comps)
    
    return timeFormatter.stringFromDate(date)
}()

You can use this for setup of complex service objects, too, of course.

showWindowService = {
    let aggregation = Aggregation(appRepository: appRepository, dataSource: dataSource)
    let interactor = Interactor(aggregation: aggregation)
    let analyticsWindowController = AnalyticsWindowController()
    let presenter = Presenter(interactor: interactor, view: analyticsWindowController)

    return ShowAnalyticsWindow(interactor: interactor, presenter: presenter)
}()