As a result of articles I read about the Option
class which helps you avoid NullPointerException's, I started to use it all over the place. Imagine something like this:
var file:Option[File] = None
and later when I use it:
val actualFile = file.getOrElse(new File("nonexisting"))
if(actualFile.getName.equals("nonexisting")) { // instead of null checking
}
else { // value of file was good
}
Doing stuff like this doesn't feel all that "right" to me. I also noticed that .get
has become deprecated. . Is this sort of stuff what you guys are doing with Option's too, or am I going the wrong way?
It's generally not a good idea to return Option
and then use getOrElse
to produce some sentinel value that means "not found". That's what Option
is designed for: to signify that a value is not found!
Option
really shows its power when used in conjunction with functional programming constructs like map
and foreach
. This is most potent when dealing with multiple options. For example, suppose I write a method that takes a string and gives me back a file, but only if the file exists and is a file not a directory:
import java.io._;
def niceFile1(s: String): File = {
val f = new File(s);
if (f.exists && !f.isDirectory) f else null
}
def niceFile2(s: String): Option[File] = {
val f = new File(s);
if (f.exists && !f.isDirectory) Some(f) else None
}
So far, using null
is easier--at least until you forget that this might give you null
and you get a NPE. Anyway, let's now try to use it.
def niceFopen1(s: String) = {
val f = niceFile1(s);
if (f!=null) new FileInputStream(f) else null;
}
def niceFopen2(s: String) = niceFile2(s).map(f => new FileInputStream(f))
Look what happened! In the former case, we had to do logic tests by hand and create temporary variables. Ugh! In the second case, map
did all the dirty work for us: None was mapped to None, and Some(file)
was mapped to Some(fileinputstream)
. Easy!
But it gets better yet. Maybe we want to find the size of a whole bunch of files:
def totalSize2(ss: Seq[String]) = {
(0L /: ss.flatMap(niceFile2)){(sum,f) => sum+f.length}
}
Wait, what is going on here--what about all the None
? Don't we have to pay attention and handle them somehow? Well, that's where flatMap
comes in: it joins together all the answers into a single list. None
is an answer of length zero, so it ignores it. Some(f)
has one answer--f
--so it puts it in the list. Then we use a fold to add up all the lengths--now that all the elements in the list are valid. Pretty nice!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With