2017-04-17 3 views
0

I SwiftHamcrestSwift nicht finden, den richtigen Typ

zu verwenden versuche habe ich eine Funktion

func equalToArray<T, S>(_ vector:Array<S>) -> Matcher<T> { 
    let v: Matcher<T> = Hamcrest.hasCount(16) 
    return v 
} 

dies ein Fehler

Error:(16, 31) 'hasCount' produces 'Matcher<T>', not the expected contextual result type 'Matcher<T>' 

SwiftHamcrest hat zwei hasCount Funktionen

public func hasCount<T: Collection>(_ matcher: Matcher<T.IndexDistance>) -> Matcher<T> 
public func hasCount<T: Collection>(_ expectedCount: T.IndexDistance) -> Matcher<T> 
gibt

Warum klagt mein Code nicht, dass er den gleichen Typ zurückgibt, der benötigt wird?

Als eine Anmerkung und möglicherweise eine andere Frage musste ich die Hamcrest hinzufügen. vor der hasCount-Methode aufrufen, da sonst versucht wird, mit der ersten Funktion

übereinstimmen Was fehlt mir mit Typen?

+1

Es sieht so aus, als ob Sie einen 'Matcher <[S]>' anstelle eines 'Matcher ' zurückgeben wollen (und dann einfach den generischen Platzhalter' T' weglassen). Obwohl ich nicht sicher bin, wofür der 'vector' Parameter ist. – Hamish

+0

@Hamish - das ist ein Cut-Down-Fall, wo ich andere Matcher wollen - also ja der Parameter ist in diesem Beispiel nicht erforderlich volleren Beispiel ist Func equalToArray (_ Vektor: Array ) -> Matcher { \t let v: Matcher = Hamcrest.hasCount (vector.count) \t return v } – Mark

Antwort

1

Ihre Methode equalToArray<T, S> weiß nicht, dass T eine Sammlung ist, so ist das Ergebnis aus den generischen hasCount(...) Methoden oben nicht zu v in Ihrer Methode zuordenbar sein (da diese Ergebnisse Matcher<T> Instanzen gezwungen zu T zurückgibt: s, die Collection sind: s). Das heißt, v ist vom Typ Matcher<T> für ein nicht eingeschränktes T, was bedeutet, dass in den Augen des Compilers z. nein T.IndexDistance für die T von v: s typ.

Wenn Sie ein Collection Typen Hindernis für die T Ihre Methode hinzufügen, sollte die Zuordnung von hasCount(...) Ergebnis v kompiliert:

func equalToArray<T: Collection, S>(_ vector: Array<S>) -> Matcher<T> { 
    let v: Matcher<T> = Hamcrest.hasCount(16) 
    return v 
} 

In einer perfekten Welt könnte der Compiler gegeben hat uns eine aufschluss Fehlermeldung, sagen entlang der Linien von

Error:(16, 31) ' hasCount ' produces ' Matcher<T> ' where ' T: Collection ', not the expected contextual result type ' Matcher<T> '


Nun, ich weiß nicht, was Sie beabsichtigen, te st hier, aber wie @ Hamish darauf hinweist, möchten Sie möglicherweise tatsächlich eine Matcher<[S]> zurückgeben und den T Platzhalter fallen lassen. Z.B. unter Verwendung der count Eigenschaft des gelieferten vector Parameters als Argument zu hasCount(...)?

func equalToArray<S>(_ vector: Array<S>) -> Matcher<[S]> { 
    return hasCount(vector.count) 
} 

Nicht hamcrest mich benutzt zu haben, könnte ich falsch sein, aber auf der Grundlage eines schnellen Skim über die SwiftHamcrest docs, glaube ich equalToArray(_:) wie oben definiert würde ein Matcher für „Vektor Gleichheit“ (WRT Semantik der Funktion konstruieren nennen) basiert nur auf der Zählung von zwei Vektoren, wobei in diesem Fall die folgende Assertion ein Erfolg

let arr1 = ["foo", "bar"] 
let arr2 = ["bar", "baz"] 

assertThat(arr1, equalToArray(arr2)) // success! ... 

Aber das ist nur eine rechten Seite sein würde, wie Sie uns den Kontext nicht gezeigt haben, wo Sie beabsichtigen, Ihre anzuwenden equalToArray(_:) Methode/Matcher; Vielleicht zeigen Sie uns nur ein minimales Beispiel, während der tatsächliche Körper von Ihnen benutzerdefinierter Matcher eher dem Namen der Methode entspricht.

+0

ja, ich weiß, das ist kein guter Vergleich von Vektoren ist - ich schneide gerade das Beispiel bis auf einen Fehler in der Hoffnung, dass das Verständnis dies würde mir im übrigen helfen - aber es tut es nicht :( – Mark

+0

Im Allgemeinen habe ich versucht, ein Array an eine Funktion unter T übergeben ... - leider nicht möglich https://bugs.swift.org/browse/SR -128 also der erste Teil Ihrer Antwort behebt meine Frage, aber der allgemeine pr oblem ist nicht reparierbar - Ich muss die externe Bibliothek neu schreiben, um Arrays zu nehmen :( – Mark

+0

@Mark ah ja, das ist eine bekannte Einschränkung, aber für viele Anwendungsfälle können Sie umgehen, indem Sie eine Überladung mit einem '[T]' bereitstellen Argument anstelle von 'T ...' (dies wäre die Überladung, wo Sie die Implementierungslogik haben), und lassen Sie die 'T ...' Methode einfach die letztere Überladung nennen. Beachten Sie, dass ein variadischer Parameter nur ein Array im Rumpf der Funktion ist, an die er übergeben wird. Siehe z.B. [this gist] (https://gist.github.com/dfib/5dcb0764f849e6d454cd57ff05109582) für ein Beispiel. Eine solche Problemumgehung kann in Ihrem Fall nützlich sein. – dfri

Verwandte Themen