Is there a way to avoid having to wrap a potentially null result inside another option when mapping from an option.
option.flatMap(arg => Option(arg.somePotentiallyNullValue))
Eg something like
option.optionMap(arg => arg.somePotentiallyNullValue )
I just have a lot of Java code in our codebase that means forever wrapping the results of maps in further Option calls.
What about implicit conversion from nullable type to Option
? Declare this somewhere in scope:
implicit def toOption[T](x: T) : Option[T] = Option(x)
Later the compiler will figure it out:
option.flatMap(_.somePotentiallyNullValue)
Since flatMap
expects Option[T]
as a result value, compiler uses toOption
implicit conversion like this:
option.flatMap(arg => toOption(arg.somePotentiallyNullValue))
The factory method for Option
will turn a null
into a None
:
scala> val os1: Option[String] = Option(null)
os1: Option[String] = None
Addendum
I may have misunderstood your question...
If you restrict its scope judiciously, you can use an implicit conversion:
scala> implicit def nullable2Option[T >: Null](t: T): Option[T] = if (t == null) None else Some(t)
warning: there were 1 feature warnings; re-run with -feature for details
nullable2Option: [T >: Null](t: T)Option[T]
scala> val os2: Option[String] = "foo"
os2: Option[String] = Some(foo)
scala> val nullS: String = null
nullS: String = null
scala> val os3: Option[String] = nullS
os3: Option[String] = None
This will work any time there's available type information for the compiler to use to drive the attempt to bridge a value of a nullable type to an Option
. E.g., when calling a method (where the types are always explicit).
In order to make things easier you could introduce a new type:
implicit class CheckedOption[T](val option:Option[T])
object CheckedOption {
@inline implicit def toOption[T](checkedOption:CheckedOption[T]):Option[T] =
checkedOption.option.flatMap(Option.apply)
}
Then in your code, where you use the option instance you do something like this:
def use(o:CheckedOption[String]) = {
o map { value =>
value + "-Some"
} getOrElse "None"
}
val option1:Option[String] = Some(null)
val option2:Option[String] = Some("foo")
use(option1) //> res0: String = None
use(option2) //> res1: String = foo-Some