This morning, I've been writing some code to read test data from the filesystem, using resources. Following David's lead on showing Java-Scala code, here's a typical Java take on it, note that I need to handle the case of reading the file in IntelliJ differently than I do in the build (IntelliJ now places resources in a subdirectory per module):
def dataFile(path: String): FilePath = {
val resource = getResource(path)
if (resource == null) {
val intellijResource = getResource("furnace/" + path)
if (intellijResource == null) {
error("No resource found at '" + path + "' or 'furnace/" + path + "'")
} else {
intellijResource
}
} else {
resource
}
}
def getResource(path: String) = Foo.getClass.getResource(path)
Now, here's the code rewritten using
Option
for handling a null
returned from getResource
(apologies for formatting). I'm using Scalaz's OptionW
, as it provides a nice (implicit) conversion from null
to an Option
(onull
) and for throwing an error on None
(err
). As an aside, these would make a fine addition to the standard API.
def dataFile(path: String): FilePath = dataFileFromAntBuild(path)
def dataFileFromAntBuild(path: String) = getResource(path).getOrElse(dataFileFromIntelliJ(path))
def dataFileFromIntelliJ(path: String) = {
val intellijPath = "furnace" + path
onull(getResource(intellijPath)).err("No resource found at '" + path + "' or '" + intellijPath + "'")
}
def getResource(path: String) = Foo.getClass.getResource(path)
This code is nicer than the first as it explicitly shows that you're sequencing through the nullness and is much more concise (we could make it more concise too if we wish).
For those still stuck in Javaland, there's always Functional Java's Option to achieve a similar thing (though with more verbosity).