Вызов первичного конструктора с несколькими неявными вызовами параметров из Java

У меня есть класс Scala, который возвращает максимум входного типа IN с помощью задания MR в Apache Spark. Этот класс работает нормально, если я вызываю его из Scala, и он работает следующим образом:

// Class
class TypedMax[IN, T](val f: IN => T)(implicit ev$1: T => Ordered[T], ev$2: TypeTag[T])
  extends Aggregator[IN, T, T] {

  override def zero: T = null.asInstanceOf[T]
  override def reduce(b: T, a: IN): T = if (b > f(a)) b else f(a)
  override def merge(b1: T, b2: T): T = if (b1 > b2) b1 else b2
  override def finish(reduction: T): T = reduction
}

// Call function
def max[IN, T](f: IN => T)(implicit ev$1: T => Ordered[T], ev$2: TypeTag[T]): TypedColumn[IN, T] =
    new TypedMax[IN, T](f).toColumn

Теперь я хотел бы сделать это также из Java, но у меня есть некоторые трудности с передачей неявных параметров. Я знаю, что неявные параметры можно передать, добавив их в список аргументов в Java, но неявные параметры есть в Scala. Поэтому я пытаюсь сделать следующее:

class TypedMax[IN, T](val f: IN => T)(implicit ev$1: T => Ordered[T], ev$2: TypeTag[T])
  extends Aggregator[IN, T, T] {

  override def zero: T = null.asInstanceOf[T]
  override def reduce(b: T, a: IN): T = if (b > f(a)) b else f(a)
  override def merge(b1: T, b2: T): T = if (b1 > b2) b1 else b2
  override def finish(reduction: T): T = reduction

  // Java api support
  def this(f: MapFunction[IN, java.lang.Double]) =
    this(x => f.call(x).asInstanceOf[T])(ev$1: T => Ordered[T], ev$2: TypeTag[T])

Который затем можно вызвать из Java:

public static <T> TypedColumn<T, Double> max(MapFunction<T, Double> f) {
  return new TypedMax<T, Double>(f).toColumn();
}

Я пробовал много перестановок передачи имплицитов из вспомогательного конструктора, используя implicityimplicit и играть с запятыми и круглыми скобками. Однако всегда жалуется, что ev$1 и ev$2 не найдены. Я должен передать параметры, однако, потому что в противном случае это будет ошибка:

Error:(135, 5) No implicit view available from T => Ordered[T].
    this(x => f.call(x).asInstanceOf[T])
Error:(135, 5) not enough arguments for constructor TypedMax: (implicit ev$1: T => Ordered[T], implicit ev$2: reflect.runtime.universe.TypeTag[T])org.apache.spark.sql.execution.aggregate.TypedMax[IN,T].
Unspecified value parameters ev$1, ev$2.
    this(x => f.call(x).asInstanceOf[T])

И если я попробую:

def this(f: MapFunction[IN, T]) =
  this(x => f.call(x))(T => Ordered[T], TypeTag[T])

Результат:

Error:(135, 38) value Ordered of type scala.math.Ordered.type does not take type parameters.
    this(x => f.call(x))(T => Ordered[T], TypeTag[T])
Error:(135, 50) missing argument list for method apply in object TypeTag
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `apply _` or `apply(_,_)` instead of `apply`.
    this(x => f.call(x))(T => Ordered[T], TypeTag[T])

Что я упускаю / недоразумение? Спасибо!

1 ответ

T => Ordered[T] не означает, что вы думаете, что это означает, это создает Function1 с аргументом T и тело scala.math.Ordered.apply[T], Вместо этого попробуйте следующее:

def this(f: MapFunction[IN, T], e: MapFunction[T, Ordered[T]], tt: TypeTag[T]) =
  this(x => f.call(x))(x => e.call(x), tt)

(Я не совсем уверен, если вы сможете материализовать TypeTag[T] из Явы)

Другие вопросы по тегам