Hiding generic parameters in a initializer?

I have a complicated struct that has multiple generic type parameters. But some simpler init calls don't need to specify them all. Ideally the caller of the simpler init wouldn't have to think about these type parameters.

Boiled down:

struct FancyThing<X, Y, Z> {
    let x: X
    let ys: [Y]
    let zs: [Z]
    init(x: X, ys: [Y], zs: [Z]) {
        self.x = x; self.ys = ys; self.zs = zs
    }
    
    /// A simplified init
    init(y: Y) {
        self.init(x:10 as! X, ys:[y], zs:[true, false] as! [Z])
    }
}

let thing0 = FancyThing(x:1, ys:[1,2], zs:["a", "b"])
print(thing0)
// But now the user has to declare these implementation details (Int, Bool)
let thing1 = FancyThing<Int,Double,Bool>(y: 3.14)
// I'd like to write simply:
let thing1 = FancyThing(y: 3.14)  // Does not compile.
print(thing1)

Is a helper function like this the only way to do it?

func makeFancyThing<Y>(y: Y) -> FancyThing<Int,Y,Bool> {
    .init(y: y)
}
let thing1 = makeFancyThing(y: 3.14)

You can use type constraints on the initializer:

struct FancyThing<X, Y, Z> {
    let x: X
    let ys: [Y]
    let zs: [Z]
  
    init(x: X, ys: [Y], zs: [Z]) {
        self.x = x; self.ys = ys; self.zs = zs
    }
    
    /// A simplified init
    init(y: Y) where X == Int, Z == Bool {
        self.init(x: 10, ys: [y], zs: [true, false])
    }
}
5 Likes

Perfect, thanks!

1 Like