19 Stimmen

Konnte keinen impliziten Wert für das Beweisparameter des Typs scala.reflect.ClassManifest[T] finden.

Es scheint, dass ich etwas Wichtiges nicht verstehe, vielleicht über Löschung (verdammt).

Ich habe eine Methode, mit der ich ein Array der Größe n mit Werten aus gen erstellen wollte:

def testArray[T](n: Int, gen: =>T) {
  val arr = Array.fill(n)(gen)
  ...
}

Und verwende es zum Beispiel so:

testArray(10, util.Random.nextInt(10))

Aber ich erhalte den Fehler:

scala: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T]
val arr = Array.fill(n)(gen)
                       ^

Bitte erkläre, was ich falsch gemacht habe, warum dieser Fehler auftritt und welche Art von Code er unmöglich macht?

14voto

drexin Punkte 24117

Dies liegt daran, dass im testArray der konkrete Typ von T zur Compile-Zeit nicht bekannt ist. Ihre Signatur muss wie folgt aussehen: def testArray[T : ClassManifest](n: Int, gen: =>T). Dadurch wird ein impliziter Parameter vom Typ ClassManifest[T] zu Ihrer Methode hinzugefügt, der automatisch an den Aufruf von testArray übergeben wird und dann weiter an den Aufruf von Array.fill. Dies wird als Kontextbindung bezeichnet.

5voto

EECOLOR Punkte 11104

Die Methode Array.fill hat folgende Signatur:

def fill[T](n: Int)(elem: => T)(implicit arg0: ClassManifest[T]): Array[T]

Um eine Instanz von ClassManifest[T] zu erhalten, müssen Sie den konkreten Typ kennen. Ein ClassManifest kann wie folgt erhalten werden:

implicitly[ClassManifest[String]]

Ein ClassManifest ist implizit für jeden konkreten Typ verfügbar.

Für jeden implicit Fehler können Sie die benötigten Impliziten dem Methode mit dem Typ-Parameter hinzufügen:

def wrap[T](n:Int)(elem: => T)(implicit c:ClassManifest[T], o:Ordering[T])

Wenn Sie nicht selbst ClassManifest oder Ordering eingeführt haben, haben die Autoren der Bibliothek (höchstwahrscheinlich) vernünftige Standards für Sie bereitgestellt.

Wenn Sie die Methode wrap aufrufen würden:

wrap(2)(3)

Wird dies erweitert wie folgt:

wrap[Int](2)(3)(implicitly[ClassManifest[Int]], implicitly[Ordering[Int]])

Wenn Sie hier eine benutzerdefinierte Klasse Person eingeführt hätten, würden Sie einen Fehler erhalten, da keine implizite Instanz von Ordering[Person] gefunden wurde. Die Autoren der Bibliothek konnten nicht wissen, wie man Person ordnet. Sie könnten dies wie folgt lösen:

class Person

implicit val o = new Ordering[Person] { // Implementieren der benötigten Methoden }

wrap(2)(new Person)

Der Scala-Compiler sucht in verschiedenen Bereichen nach Impliziten, eine Ordering würde normalerweise nicht so spezifiziert werden. Ich empfehle Ihnen, die implizite Auflösung im Internet nachzuschlagen, um mehr darüber zu erfahren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X