Last active
June 27, 2018 02:19
-
-
Save jessesquires/4b6e76bb580600a85c40 to your computer and use it in GitHub Desktop.
Swift optional generic parameters?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol FactoryAType { | |
typealias Product | |
} | |
protocol FactoryBType { | |
typealias Product | |
} | |
struct CombinedFactory<T: FactoryAType, U: FactoryBType where T.Product == U.Product> { | |
let factoryA: T | |
let factoryB: U? | |
init(factoryA: T, factoryB: U? = nil) { | |
self.factoryA = factoryA | |
self.factoryB = factoryB | |
} | |
} | |
struct IntAFactory: FactoryAType { | |
typealias Product = Int | |
} | |
struct IntBFactory: FactoryBType { | |
typealias Product = Int | |
} | |
let fa = IntAFactory() | |
let fb = IntBFactory() | |
let allGood = CombinedFactory(factoryA: fa, factoryB: fb) | |
// Does not work: | |
// Cannot invoke initializer for type 'CombinedFactory<_, _>' with an argument list of type '(factoryA: IntAFactory)' | |
let combinedFactory = CombinedFactory(factoryA: fa) | |
// This works: | |
// But this is awkward. I don't want to have to specify B if it is nil | |
let workingFactory = CombinedFactory<IntAFactory, IntBFactory>(factoryA: fa) |
my experience is that when you find yourself here, the mistake happened much earlier and you shouldn't even have been here.
This is sooooo truuuuuue
Updated my playing around here: https://gist.github.com/rnapier/44bf23300959cca9c43f
Thanks guys!
So the full context is https://github.com/jessesquires/JSQDataSourcesKit.
"Factory" is already sounding like something un-Swifty.
Ha -- probably because I'm trying to make Cocoa less cubersome. I hate that UICollectionView/UITableView delegates/dataSources are littered with @optional
methods 😢
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In most cases, if
U
is not passed, then this shouldn't be aCombinedFactory
. It should just anAFactory
. Just make sure thatAFactory
andCombinedFactory
conform to the same protocol so they can be used interchangeably. It'd be helpful to see the actual use case; my experience is that when you find yourself here, the mistake happened much earlier and you shouldn't even have been here. Most common cause is using a struct and methods when you could have just used a closure and avoided all the intermediate types.If you really need the idea of "no such
U
" then you need to say so:Then you can use it like:
or create a function like:
At this point, however, you do slam into numerous weaknesses in the compiler. You can't make
aOnly
into ainit
. You can't even make it into a classstatic
. Swift just doesn't have the ability to haveinit
explicitly provide its associated types (I don't believe there's any deep reason for that to be impossible, but it is).I'm very interested in what the underlying problem is, though. "Factory" is already sounding like something un-Swifty.