scala: почему код возвращает List [Any], а не List [String]? - PullRequest
1 голос
/ 19 января 2020

Я пытаюсь выучить scala, и меня смущает одна вещь:

Почему следующий код возвращает List[Any], а не List[String]

def listToLowerCase(l: List[String]) = l.map(s=>if(s != null) s.toLowerCase) 

потому что когда строка null я даже не вызываю lowerCase функцию? но не должен ли он ничего не вернуть?

Ответы [ 2 ]

3 голосов
/ 19 января 2020

В Scala большинство структур управления являются выражениями , а не выражениями .
Таким образом, if-else должен возвращать значение. Поскольку у вас нет ветки else, компилятор вставляет эту else (). Таким образом, ваш код иногда возвращает Строки , другие времена Единица , и LUB из этих двух типов равен Любой .

Есть несколько способов решить эту проблему, один из них - убедиться, что в списке нет nulls до map (обычно в Scala мы никогда не ожидаем null) . Другое - возвращать какое-то значение по умолчанию, если строка, например, null и пустая строка. Другой способ - использовать тип данных Option для представления пропущенных значений.

Вот несколько советов:

list.filter(_ != null).map(_.toLowerCase)
list.collect { case str if (str != null) => str.toLowerCase }
list.map(str => if (str != null) str.toLowerCase else "")
list.map(str => Option(str).map(_.toLowerCase))
list.map(str => Option(str).map(_.toLowerCase)).getOrElse("")
list.map(str => Option(str).fold(ifEmpty = "")(_.toLowerCase))
list.flatMap(str => Option(str).map(_.toLowerCase))

Я бы порекомендовал вам последние четыре, как прямые манипулирование null в Scala не рекомендуется. За исключением случаев, когда производительность является обязательной, а выделение Option слишком дорого для вашего варианта использования (что бывает редко) .

1 голос
/ 19 января 2020

Когда else часть условного выражения отсутствует * печатает на Unit, следовательно, наименьшая верхняя граница из них равна Any. Согласно SLS

Краткая форма условного выражения исключает остальную часть. Условное выражение if (?1) ?2 оценивается так, как если бы оно было if (?1) ?2 else ().

Обратите внимание, что мы могли бы отфильтровать null перед нижним регистром, как, например,

List[String]("AA", null).flatMap(Option(_)).map(_.toLowerCase)
// res0: List[String] = List(aa)

, потому что Option(null) это None.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...