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 № 1Você 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 tornaNone
se o valor fornull
ouSome(...)
com o valor caso contrário - Da mesma forma, ao envolver algo que pode gerar uma exceção no
Try
, torna-seFailure
com exceção, ouSuccess
com o valor toOption
método converteTry
paraOption
de uma maneira direta:Failure
torna-seNone
,Success
torna-seSome
- na compreensão, se qualquer dos quatro
Option
s retornaNone
(ou seja, um deles eranull
falhou ao analisar um número), toda a instrução retornaNone
, e somente se cada dos quatro rende um valor, eles são passados para oYellowAccount
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
)
}