/ / Como fazer verificações nulas no Scala de maneira idiomática? - scala

Como fazer verificações de nulos no Scala de uma maneira idiomática? - scala

case class Account(
val name: String,
val uuid: String,
val lat: Double,
val lng: Double
)
}

object Account {
def create(row: Row): Option[YellowAccount] = {
val name = row.getAs[String]("store_name")
val uuid = row.getAs[String]("uuid")
val latO = row.getAs[String]("latitude")
val lngO = row.getAs[String]("longitude")

// How do you do null checks here in an idiomatic way?
if (latO == null || lngO == null) {
return None
}

Some(YellowAccount(name, uuid, latO.toDouble, lngO.toDouble))
}

}

lat / long são campos obrigatórios em Account. Como você faz verificações nulas de maneira idiomática?

Respostas:

4 para resposta № 1

Você pode usar Option tipo para manipular null valores. Você apenas quebra um valor anulável em Option e então você pode padronizar a correspondência nele ou em outra coisa. No seu exemplo, acho que a maneira mais concisa de combinar 4 valores anuláveis ​​é pela compreensão:

import scala.util.Try

object Account {
def create(row: Row): Option[YellowAccount] = {
for {
name <- Option( row.getAs[String]("store_name") )
uuid <- Option( row.getAs[String]("uuid") )
latO <-    Try( row.getAs[String]("latitude").toDouble ).toOption
lngO <-    Try( row.getAs[String]("longitude").toDouble ).toOption
} yield
YellowAccount(name, uuid, latO, lngO)
}
}

EDITAR

Outra coisa aqui é _.toDouble conversão, que pode gerar uma exceção se falhar ao analisar a sequência, para que você possa envolvê-la Try em vez disso (atualizei o código acima).

EDIT2

Para esclarecer o que está acontecendo aqui:

  • quando você quebra um valor em Option se torna None se o valor for nullou Some(...) com o valor caso contrário
  • Da mesma forma, ao envolver algo que pode gerar uma exceção no Try, torna-se Failure com exceção, ou Success com o valor
  • toOption método converte Try para Option de uma maneira direta: Failure torna-se None, Success torna-se Some
  • na compreensão, se qualquer dos quatro Options retorna None (ou seja, um deles era null falhou ao analisar um número), toda a instrução retorna None, e somente se cada dos quatro rende um valor, eles são passados ​​para o YellowAccount construtor

0 para resposta № 2

Como a outra resposta sugere, você pode usar Option para lidar com possíveis nulos. Você não pode usar for compreensão da maneira que é sugerida lá, mas existem várias maneiras de contornar isso. O mais fácil, provavelmente, é .zip as duas opções juntas e mapeie o resultado:

  Option(row.getAs[latitude])
.zip(Option(row.getAs[String]("longitude")))
.map { case (lat, long) =>
YellowAccount(
row.getAs[String]("store_name"),
row.getAs[String]("uuid"),
lat.toDouble,
long.toDouble
)
}