Default init


« Building on our Foundation

List map/flatMap »

I just learned something I should have known but didn't and I want to share it with you.

A while back we looked at turning the free function implementation of IntSet into a struct.

We started with something like this.

struct IntSet {
    let contains: (Int) -> Bool
}

This includes a property named contains and a default init() that accepts contains.

I wanted to add a way of constructing a set from a range. So I wanted to add this to IntSet.


struct IntSet {
    let contains: (Int) -> Bool
    
    init(withRangeFrom lower: Int, to upper: Int) {
        contains = {x in
            (x >= lower) && (x <= upper)
        }
    }
}

The problem with this is that it prevents the default init from being generated. So we had to explicitly insert the default init like this.


struct IntSet {
    let contains: (Int) -> Bool
    
        init(contains: @escaping (Int) -> Bool) {
        self.contains = contains
    }

    init(withRangeFrom lower: Int, to upper: Int) {
        contains = {x in
            (x >= lower) && (x <= upper)
        }
    }
}

or did we....

If we instead add our additional init in an extension then the automatically generated one is still provided.


struct IntSet {
    let contains: (Int) -> Bool
}

extension IntSet {
    init(withRangeFrom lower: Int, to upper: Int) {
        contains = {x in
            (x >= lower) && (x <= upper)
        }
    }
}

Much nicer.

2018