#scala #apache-spark #implicit
#scala #apache-spark #неявный
Вопрос:
У меня есть некоторый код scala / spark, который выглядит следующим образом:
import sqlContext.implicits._
val join: (Dataset[MyCaseClassA], Dataset[MyCaseClassB]) => Dataset[AB] = (a, b) =>
a.joinWith(b,
a("prop_a1") === b("prob_b1"),
"left"
) //more code...
Это отлично работает и компилируется и все такое. Но, допустим, я хочу заняться некоторым функциональным программированием, поэтому я реорганизовал все это, чтобы:
import sqlContext.implicits._
val join: (Unit => Dataset[MyCaseClassA], Unit => Dataset[MyCaseClassB]) => Dataset[AB] = (a, b) =>
a(Unit).joinWith(b(Unit),
a("prop_a1") === b("prob_b1"),
"left"
) //more code...
AFAIKT это должно работать просто отлично. Однако в конечном итоге происходит то, что IntelliJ сразу становится серым import sqlContext.implicits._
, и методы ===
перестают разрешаться с помощью value === is not a member of org.apache.spark.sql.Dataset
.
Поэтому по какой-то причине import sqlContext.implicits._
просто не работает при передаче функциональных аргументов. Мои вопросы:
- Почему неявный импорт перестает работать?
- Что я могу сделать, чтобы импорт работал и по-прежнему использовал аргументы функции?
Ответ №1:
В основном дело не в последствиях, а в несоответствии типов (а последствия очень чувствительны к типам).
Unit
в a(Unit)
, b(Unit)
является сопутствующим объектом абстрактного класса Unit
. У него нет типа Unit
(у него есть тип Unit.type
). Это ()
то, что имеет тип Unit
.
a(Unit)
, b(Unit)
компилируйте только потому, что в Scala любой тип (например Unit.type
) может быть преобразован в Unit
.
Также вы не можете писать a("prop_a1")
, b("prob_b1")
потому что a
b
это функции из Unit
, к которым вы не можете применить String
.
Итак, хотя
val join: (Unit => Dataset[MyCaseClassA], Unit => Dataset[MyCaseClassB]) => Dataset[AB] = (a, b) =>
a(Unit).joinWith(b(Unit),
a(Unit)("prop_a1") === b(Unit)("prob_b1"),
"left"
) //more code...
скомпилировать (аналогично даже
val join: (Unit => Dataset[MyCaseClassA], Unit => Dataset[MyCaseClassB]) => Dataset[AB] = (a, b) =>
a(1).joinWith(b("A"),
a(true)("prop_a1") === b(???)("prob_b1"),
"left"
) //more code...
будет компилироваться) кажется, вы на самом деле имели в виду
val join: (Unit => Dataset[MyCaseClassA], Unit => Dataset[MyCaseClassB]) => Dataset[AB] = (a, b) =>
a(()).joinWith(b(()),
a(())("prop_a1") === b(())("prob_b1"),
"left"
) //more code...
Также немного странно принимать, Unit
обычно Unit
возвращается.
Вы могли бы написать
val join: (() => Dataset[MyCaseClassA], () => Dataset[MyCaseClassB]) => Dataset[AB] = (a, b) =>
a().joinWith(b(),
a()("prop_a1") === b()("prob_b1"),
"left"
) //more code...
Здесь () => ...
он же Function0[...]
— это тип функций без аргументов.
Или вы можете писать с аргументами по имени
val join: (=> Dataset[MyCaseClassA], => Dataset[MyCaseClassB]) => Dataset[AB] = (a, b) =>
a.joinWith(b,
a("prop_a1") === b("prob_b1"),
"left"
) //more code...