Reputation: 3455
I am working with swift-snapshot-testing and found a problem about Generic function parameter default value.
The framework provide a method like this:
func verifySnapshot<Value, Format>(matching value: Value,
as snapshotting: Snapshotting<Value, Format>,
snapshotDirectory: String? = nil) -> String?
where Snapshotting
is a generic struct like this:
struct Snapshotting<Value, Format> {}
extension Snapshotting where Value == UIViewController, Format == UIImage {
static var image: Snapshotting<UIViewController, UIImage> {
:
}
}
extension Snapshotting where Value == UIView, Format == UIImage {
static var image: Snapshotting<UIView, UIImage> {
:
}
}
I want to create a helper method and this works:
func verify<Value, Format>(matching value: Value,
as snapshotting: Snapshotting<Value, Format>) {
let snapshotDirectory = "/path"
let failure = verifySnapshot(matching: value,
as: snapshotting,
snapshotDirectory: snapshotDirectory)
print(failure ?? "Done!")
}
But when I want to give snapshotting
a default parameter value .image
, it does not compile for the error Ambiguous reference to member 'image'
func verify<Value, Format>(matching value: Value,
as snapshotting: Snapshotting<Value, Format> = Snapshotting<Value, Format>.image)
My question is: can Swift infer the generic type Format
for default parameter value?
Upvotes: 2
Views: 106
Reputation: 3455
Ref to @Rob Napler's answer I made a work-round to make the interface looks like with default value:
///interface to accept snapshotting argument
func verify<Value, Format>(matching value: Value,
as snapshotting: Snapshotting<Value, Format>)
///interfaces to accept specific kind of value
func verify(matching value: UIView)
func verify(matching value: UIViewController)
:
:
and we can call it like
verify(matching: aView)
or
verify(matching: aView, as: .image)
Upvotes: 0
Reputation: 299355
The main problem here is that .image
does not exist for every <Value, Format>
pair. It only exists for <UIViewController, UIImage>
, and <UIView, UIImage>
. To assign a default here, it has to be applicable to every way that verify
can be called.
Default parameters can always be expressed as a separate function with fewer parameters, so you just need to add the desired overloads rather than the default value.
func verify(matching value: UIViewController) {
verify(matching: value, as: .image)
}
func verify(matching value: UIView) {
verify(matching: value, as: .image)
}
Upvotes: 1