I've seen a lot of times code like this:
...
val aString: String = someFunctionDataReturnsAString()
...
if (someCondition) Some(aString)
else
...
Is it right to create a new Option
using Some(aString)
?
What if for some reason turns out the value of aString
is null
?
Wouldn't be good replacing the if
sentence with:
if (someCondition) Option(aString)
Because:
val a = Some("hello")
val b: String = null
val c = Some(b)
val d = Option(b)
println(a)
println(c)
println(d)
Will print in the console:
Some(hello)
Some(null)
None
Looks like a better idea to use Option
when passing a string as parameter, so in case the string is null
the value of the Option
will be None
.
I've seen code to be reviewed and I think with cases like this a comment should be added asking for replacing Some(aString)
with Option(aString)
.
CodePudding user response:
You are right. Assuming your string can be null, it's recommended to use Option(aString)
:
def apply[A](x: A): Option[A]
An
Option
factory which createsSome(x)
if the argument is notnull
, andNone
if it isnull
.
x
- the valuereturns -
Some(value)
ifvalue != null
,None
ifvalue == null
Class Option
mentions that both have their use case, so the programmer has the last say which one is better suited for his particular need:
Interacting with code that can occasionally return null can be safely wrapped in
scala.Option
to becomeNone
andscala.Some
otherwise.
On a personal note, since strings are immutable and you can't really have uninitialized strings (because Scala always requires you to initialize them - unless you use var
variables, which is not the recommended way to program in Scala anyway), you'll rarely actually encounter null strings in your code.
That being said, one can still decide to go for Option(aString)
every time, and it's perfectly fine.
CodePudding user response:
Normally it's ok to replace Some.apply
with Option.apply
(and safer).
But, although normally this is not a big deal (and let's avoid premature optimizations), there can be minor runtime overhead for Option.apply
, since we add another branching instead of just wrapping.
Generally, you could split your project into pure FP part (it's ok to assume that your strings are not null
there and use Some.apply
, also Some.apply
is canonical monadic pure
for Option
) and part where you interact with the outer world, with Java libraries etc. (it's more safely to use Option.apply
there).
But we should keep in mind that Some.apply
returns Some[A]
while Option.apply
returns its supertype Option[A]
. Normally it's ok but sometimes in type-level calculations this can be too rough if you need to know precise type at compile time. See for example Shapeless and annotations , how to use shapeless to detect field type annotation