Questo è un argomento molto vecchio ma carino!
È vero che la conversione di qualsiasi risultato non eccezionale di Try to Option si tradurrà in un Some ...
scala> Try(null).toOption
res10: Option[Null] = Some(null)
... perché Try non riguarda il controllo del nullability ma solo un modo per gestire funzionalmente le eccezioni.
L'utilizzo di Try per catturare un'eccezione e la conversione di questa in un'opzione per comodità mostrerà Nessuno solo nel caso in cui si verifichi un'eccezione.
scala> Try(1/0).toOption
res11: Option[Int] = None
Vuoi preservare i valori che provengono da Try. Potrebbe essere nullo.
Ma è anche vero che la libreria standard a volte è abbastanza confusa ...
scala> Try(null).toOption
res12: Option[Null] = Some(null)
scala> Option(null)
res13: Option[Null] = None
Questo comportamento è un po 'incoerente ma in qualche modo riflette l'uso intenzionale di Try e Option.
Usi try per ottenere tutto ciò che esce da un'espressione che può generare eccezioni e non ti interessa l'eccezione stessa.
Il valore che potrebbe risultare potrebbe essere nullo. Se toOption ha dato None, non potresti distinguere tra un'eccezione e un null , e questo non è carino!
Standalone, usi Option per incapsulare l'esistenza o meno di qualcosa. Quindi in quel caso Some (null) è None, e questo ha senso, perché null in quel caso rappresenta l'assenza di qualcosa. Non c'è ambiguità qui.
È importante notare che in ogni caso la trasparenza referenziale non viene interrotta poiché .toOption non è la stessa cosa di Option ()
Se si ha realmente bisogno di far rispettare SIA sicurezza rispetto alle eccezioni E nulla la sicurezza, e il codice davvero non ha bisogno di distinzione fra nullo e un'eccezione , è sufficiente combinare entrambi i paradigmi! Perché beh, è quello che vuoi, giusto?
Puoi farlo in un modo ...
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)
... oppure un'altra ...
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)
... o il ridicolmente più brutto di loro altri ...
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)