Scala компилятору не удалось определить тип внутри лямбда-функции Spark - PullRequest
1 голос
/ 11 июля 2020

Предположим, что у меня есть этот код Spark, написанный на Scala 2,12

    val dataset = spark.emptyDataset[String]

    dataset.foreachPartition( partition => partition.foreach {
      entry: String => println(entry)
    })

Когда я запускаю код, компилятор выдал эту ошибку


[info] Compiling 1 Scala source to <path>/scala-2.12/classes ...
[error] Code.scala:11:52: value foreach is not a member of Object
[error]     empty.foreachPartition( partition => partition.foreach{
[error]                                                    ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 1 s, completed Jul 11, 2020 1:43:41 AM


Почему компилятор partition как Object вместо Iterator[String]?

Мне нужно вручную добавить тип partition, чтобы код работал.

    val dataset = spark.emptyDataset[String]

    dataset.foreachPartition( (partition:Iterator[String]) => partition.foreach {
      entry: String => println(entry)
    })

1 Ответ

4 голосов
/ 11 июля 2020

Это из-за двух перегруженных версий foreachPartition и Java - Scala взаимодействия.

Если бы код был только в Scala (это минимальный код и не зависит от Spark)

val dataset: Dataset[String] = ???

dataset.foreachPartition(partition => ???)

class Dataset[T] {
  def foreachPartition(f: Iterator[T] => Unit): Unit = ???
  def foreachPartition(func: ForeachPartitionFunction[T]): Unit = ???
}

trait ForeachPartitionFunction[T] extends Serializable {
  def call(t: Iterator[T]): Unit
}

, тогда будет выведен тип partition (как scala.collection.Iterator[String]).

Но в фактическом коде Spark ForeachPartitionFunction - это интерфейс Java, метод которого call принимает java.util.Iterator[String].

Таким образом, оба варианта

dataset.foreachPartition((
  (partition: scala.collection.Iterator[String]) => ??? 
): Iterator[String] => Unit)

dataset.foreachPartition((
  (partition: java.util.Iterator[String]) => ??? 
): ForeachPartitionFunction[String])

приемлемы, и компилятор не может сделать вывод о типе partition.

И вывод в Scala local, поэтому после того, как компилятор увидит partition => partition.foreach...java.util.Iterator[String] не имеет метода foreach), уже слишком поздно возвращаться к вводу partition.

...