J'essaie d'écrire des cas d'utilisation pour Apache Flink. Une erreur que je rencontre assez souvent est
could not find implicit value for evidence parameter of type org.Apache.flink.api.common.typeinfo.TypeInformation[SomeType]
Mon problème est que je ne peux pas vraiment clouer quand ils se produisent et quand ils ne le font pas.
L'exemple le plus récent serait le suivant
...
val largeJoinDataGen = new LargeJoinDataGen(dataSetSize, dataGen, hitRatio)
val see = StreamExecutionEnvironment.getExecutionEnvironment
val newStreamInput = see.addSource(largeJoinDataGen)
...
où LargeJoinDataGen extends GeneratorSource[(Int, String)]
et GeneratorSource[T] extends SourceFunction[T]
, tous deux définis dans des fichiers séparés.
Lorsque j'essaie de construire cela, je reçois
Error:(22, 39) could not find implicit value for evidence parameter of type org.Apache.flink.api.common.typeinfo.TypeInformation[(Int, String)]
val newStreamInput = see.addSource(largeJoinDataGen)
1. Pourquoi y a-t-il une erreur dans l'exemple donné?
2. Quelle serait une directive générale lorsque ces erreurs se produisent et comment les éviter à l'avenir?
P.S .: premier scala et premier projet flink donc soyez patient
Cela se produit principalement lorsque vous avez du code utilisateur, c'est-à-dire une source ou une fonction de carte ou quelque chose de cette nature qui a un paramètre générique. Dans la plupart des cas, vous pouvez résoudre ce problème en ajoutant quelque chose comme
implicit val typeInfo = TypeInformation.of(classOf[(Int, String)])
Si votre code se trouve dans une autre méthode qui a un paramètre générique, vous pouvez également essayer d'ajouter un contexte lié au paramètre générique de la méthode, comme dans
def myMethod[T: TypeInformation](input: DataStream[Int]): DataStream[T] = ...
Vous pouvez effectuer une importation au lieu d'implicites
import org.Apache.flink.streaming.api.scala._
Cela vous aidera également.
Mon problème est que je ne peux pas vraiment clouer quand ils se produisent et quand ils ne le font pas.
Ils se produisent lorsqu'un paramètre implicite est requis. Si nous regardons la définition de la méthode, nous voyons:
def addSource[T: TypeInformation](function: SourceFunction[T]): DataStream[T]
Mais nous ne voyons aucun paramètre implicite défini, où est-il?
Lorsque vous voyez une méthode polymorphe où le paramètre type est de la forme
def foo[T : M](param: T)
Où T
est le paramètre de type et M
est un lié au contexte . Cela signifie que le créateur de la méthode demande un paramètre implicite de type M[T]
. Il équivaut à:
def foo[T](param: T)(implicit ev: M[T])
Dans le cas de votre méthode, elle est en fait développée pour:
def addSource[T](function: SourceFunction[T])(implicit evidence: TypeInformation[T]): DataStream[T]
C'est pourquoi vous voyez le compilateur se plaindre, car il ne peut pas trouver le paramètre implicite dont la méthode a besoin.
Si nous allons sur le wiki Apache Flink, sous Type Information nous pouvons voir pourquoi cela se produit:
Aucune valeur implicite pour l'erreur de paramètre de preuve
Dans le cas où
TypeInformation
n'a pas pu être créé, les programmes ne parviennent pas à compiler avec une erreur indiquant "n'a pas pu trouver de valeur implicite pour le paramètre de preuve de type TypeInformation". Une raison fréquente si que le code qui génère leTypeInformation
n'a pas été importé. Veillez à importer l'intégralité du package flink.api.scala. import org.Apache.flink.api.scala ._
Pour les méthodes génériques, vous devrez également les obliger à générer un TypeInformation
sur le site d'appel:
Pour les méthodes génériques, les types de données des paramètres de fonction et le type de retour peuvent ne pas être les mêmes pour chaque appel et ne sont pas connus sur le site où la méthode est définie. Le code ci-dessus entraînera une erreur indiquant qu'il n'y a pas suffisamment de preuves implicites disponibles. Dans de tels cas, les informations de type doivent être générées sur le site d'invocation et transmises à la méthode. Scala propose des paramètres implicites pour cela.
Pour vos types, cela signifie que si la méthode d'appel est générique, elle doit également demander le contexte lié à son paramètre de type.