Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return None in Scala

For my first Scala program, I am trying to write a small utility which will convert an XML file from one schema to another.

I started writing a method which will give me the file contents:

  def loadFile(filename: String, encoding: String = "utf-8"):Option[String] = {
    try
    {
      val source = scala.io.Source.fromFile(filename, encoding)
      val contents = source.mkString
      source.close()
      return Some(contents)
    }
    catch 
    {
      return None
    }

  }

But it does not compile. I get back "value apply is not a member of Nothing" and "value isDefinedAt is not a member of Nothing" as error messages from the line return None.

All the examples I can find returning an Option use matching, but this does not make sense here. I just want to not fail if I can't read the file for some reason.

What should I do in this case? Is there a pattern for doing this kind of thing in Scala?

like image 889
rumtscho Avatar asked Oct 30 '13 18:10

rumtscho


People also ask

How do I return null values in Scala?

3) Writing Scala methods Never return null . If you feel like returning a null value from a method, declare that the method will return an Option[T] (such as Option[String]), then return Some[T] and None from the method.

How do I know if Scala is none?

We can test whether an Option is Some or None using these following methods: isDefined – true if the object is Some. nonEmpty – true if the object is Some. isEmpty – true if the object is None.

What is some and none in Scala?

An Option[T] can be either Some[T] or None object, which represents a missing value. For instance, the get method of Scala's Map produces Some(value) if a value corresponding to a given key has been found, or None if the given key is not defined in the Map.

What is isDefined in Scala?

 final def isDefined: Boolean. Returns true if the option is an instance of scala. Some, false otherwise. Returns true if the option is an instance of scala.Some, false otherwise. This is equivalent to: option match { case Some(_) => true case None => false }


2 Answers

In this specific case (exception handling), I'd suggest using a Try instead.

def loadFile(filename: String, encoding: String = "utf-8"):Option[String] = {
    Try {
      val source = scala.io.Source.fromFile(filename, encoding)
      val contents = source.mkString
      source.close()
      return Some(contents)
    }.toOption
}

I would, however, recommend against catching the exception at all. You're swallowing the cause for the error by returning None: is it a FileNotFoundException? a standard IOException? was there a message with the error (Unsupported encoding comes to mind…)?

My rule of thumb is to let the caller deal with exceptions. If he doesn't care about the error itself, handling things is as easy as:

Try {loadFile("test.txt")}.toOption

Better yet, since Try has all the required methods, it can be used in a for-comprehension in a rather neat way:

for(s <- Try {loadFile("test.txt")};
    i <- Try {s.toInt}) yield i

This will result in either a Success[Int] or a Failure that contains an exception describing exactly what went wrong.

like image 156
Nicolas Rinaudo Avatar answered Sep 28 '22 09:09

Nicolas Rinaudo


There is all about "catch".

In scala it's supposed to be like this to make it compile:

  def loadFile(filename: String, encoding: String = "utf-8"):Option[String] = {
    try {
      val source = scala.io.Source.fromFile(filename, encoding)
      val contents = source.mkString
      source.close()
      Some(contents)
    } catch {
      case x: IOException =>  None
      case x => errorHandler(x) // if any other exception
    }
  }

  def errorHandler(e: Any) = None // put some logic here..

So use:

catch { case: x:ExceptionType ={ .. handling .. }}

In Scala catch is a function that accepts another function as argument. So having what you have would complain about apply function. case provides that function (PartialFunction) that catch wants. (in nutshell)

Note: All exceptions are unchecked in Scala even IOException.

like image 34
ses Avatar answered Sep 28 '22 10:09

ses