Envolvendo o método de retorno nulo em Java com a opção em Scala?


107

Suponha que eu tenha um método, session.get(str: String): Stringmas você não saiba se ele retornará uma string ou um valor nulo, porque vem de Java.

Existe uma maneira mais fácil de tratar isso no Scala em vez de session.get("foo") == null? Talvez alguma magia se aplique como ToOption(session.get("foo"))e então eu posso tratá-la no modo Scala como

ToOption(session.get("foo")) match {
    case Some(_) =>;
    case None =>;
}

4
Para obter mais dicas sobre opções, consulte blog.tmorris.net/scalaoption-cheat-sheet
Landei

Respostas:


182

O método Optiondo objeto complementar applyserve como uma função de conversão de referências anuláveis:

scala> Option(null)
res4: Option[Null] = None

scala> Option(3)   
res5: Option[Int] = Some(3)

19

O Optionobjeto tem um applymétodo que faz exatamente isso:

var myOptionalString = Option(session.get("foo"));

5

Observe que, ao trabalhar com objetos Java, não funcionará como esperado:

val nullValueInteger : java.lang.Integer = null
val option: Option[Int] = Option(nullValueInteger)
println(option)  // Doesn't work - zero value on conversion

val nullStringValue : String = null
val optionString: Option[String] = Option(nullStringValue)
println(optionString) // Works - None value

1
Corri com o scala 2.11.8. A segunda linha lançou NullPointerException. A sexta linha obteve Some (null), não None, como você esperava.
John Lin

1. Usado Some em vez de Option em optionString - Alterado na resposta original. 2. Verificado apenas em Scala
2.12.5

-3

Este é um tópico muito antigo, mas bom!

É verdade que converter qualquer resultado de Não-exceção de Tentar Opção resultará em um ...

scala> Try(null).toOption
res10: Option[Null] = Some(null)

... porque Try não é sobre verificação de nulidade, mas apenas uma maneira de lidar funcionalmente com exceções.

Usar Tentar capturar uma exceção e convertê-la em Opção por conveniência só mostrará Nenhum caso ocorra uma exceção.

scala> Try(1/0).toOption
res11: Option[Int] = None

Você deseja preservar os valores que saem do Try. Isso pode ser nulo.

Mas também é verdade que a lib padrão é bastante confusa às vezes ...

scala> Try(null).toOption
res12: Option[Null] = Some(null)

scala> Option(null)
res13: Option[Null] = None

Este comportamento é um pouco inconsistente, mas reflete o uso intencional de Try e Option.

Você usa try para obter tudo o que sai de uma expressão que pode lançar exceções e não se importa com a exceção em si.

O valor que pode resultar pode muito bem ser nulo. Se toOption fornecesse None, você não poderia diferenciar entre uma exceção e um nulo , e isso não é bonito!

Autônomo, você usa a opção para encapsular a existência ou não de algo. Então, nesse caso, Some (nulo) é Nenhum, e isso faz sentido, porque nulo nesse caso representa a ausência de algo. Não há ambigüidade aqui.

É importante ressaltar que em nenhum caso a transparência referencial não é quebrada já que .toOption não é o mesmo que Option ()

Se você realmente precisa impor AMBOS a segurança de exceção E a segurança de nulo, e seu código realmente não precisa diferenciar entre nulo e uma exceção , você só precisa combinar os dois paradigmas! Porque bem, é isso que você quer, certo?

Você pode fazer isso de uma maneira ...

scala> Try(Option(null)).getOrElse(None)
res23: Option[Null] = None

scala> Try(Option(3/0)).getOrElse(None)
res24: Option[Int] = None

scala> Try(Option(3)).getOrElse(None)
res25: Option[Int] = Some(3)

... ou outro ...

scala> Try(Option(null)).toOption.flatten
res26: Option[Null] = None

scala> Try(Option(3/0)).toOption.flatten
res27: Option[Int] = None

scala> Try(Option(3)).toOption.flatten
res28: Option[Int] = Some(3)

... ou o ridiculamente mais feio deles ...

scala> Option(Try(null).getOrElse(null))
res29: Option[Null] = None

scala> Option(Try(3/0).getOrElse(null))
res30: Option[Any] = None

scala> Option(Try(3).getOrElse(null))
res31: Option[Any] = Some(3)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.