I am trying to use SwiftHamcrest
I have a function
func equalToArray<T, S>(_ vector:Array<S>) -> Matcher<T> {
let v: Matcher<T> = Hamcrest.hasCount(16)
return v
}
This gives an error
Error:(16, 31) 'hasCount' produces 'Matcher<T>', not the expected contextual result type 'Matcher<T>'
SwiftHamcrest has two hasCount functions
public func hasCount<T: Collection>(_ matcher: Matcher<T.IndexDistance>) -> Matcher<T>
public func hasCount<T: Collection>(_ expectedCount: T.IndexDistance) -> Matcher<T>
Why is my code complaining isn't it returning the same type that is needed.
As a note and possibly a different question I had to add the Hamcrest. before the hasCount method call as otherwise it tried to match to the first function
What am I missing with types?
Your method equalToArray<T, S>
does not know that T
is a collection, so the result from the generic hasCount(...)
methods above will not be assignable to v
in your method (since these results returns Matcher<T>
instances constrained to T
:s that are Collection
:s). I.e., v
is of a type Matcher<T>
for a non-constrained T
, meaning, in the eyes of the compiler, there is e.g. no T.IndexDistance
for the T
of v
:s type.
If you add a Collection
type constraint to the T
of your method, the assignment from hasCount(...)
result to v
should compile:
func equalToArray<T: Collection, S>(_ vector: Array<S>) -> Matcher<T> {
let v: Matcher<T> = Hamcrest.hasCount(16)
return v
}
In a perfect world, the compiler could've given us a more telling error message, say along the lines of
Error:(16, 31) '
hasCount
' produces 'Matcher<T>
' where 'T: Collection
', not the expected contextual result type 'Matcher<T>
'
Now, I don't know what you're intending to test here, but as @Hamish points out, you might actually want to return a Matcher<[S]>
and drop the T
placeholder. E.g. using the count
property of the supplied vector
parameter as argument to hasCount(...)
?
func equalToArray<S>(_ vector: Array<S>) -> Matcher<[S]> {
return hasCount(vector.count)
}
Not having used Hamcrest myself, I might be mistaken, but based on a quick skim over the SwiftHamcrest docs, I believe equalToArray(_:)
defined as above would construct a matcher for "vector equality" (w.r.t. semantics of the function name) based only on the count of two vectors, in which case the following assert would be a success
let arr1 = ["foo", "bar"]
let arr2 = ["bar", "baz"]
assertThat(arr1, equalToArray(arr2)) // success! ...
But this is just a byline, as you haven't shown us the context where you intend to apply your equalToArray(_:)
method/matcher; maybe you're only showing us a minimal example, whereas the actual body of you custom matcher is more true to the method's name.