Monday, April 30, 2012

Hard because its hard or because its easy?

Some problems are hard because they're actually hard.
Some problems however are only hard because the answer is so easy that no one tells you about them.

I recently encountered a problem of the latter type while playing around with Scala's Option type.  If you are not familiar with it Option is a type that can either hold a thing or hold nothing.  So, Option[String] is either a String or its nothing (actually None in Scala).  For reasons that you probably either already know about or don't care to know this is very useful when coding in Scala.

You can say things like:
   foo match {
     case None => // handle the case where is is None
     case Some => // handle the case where there is something
}

(Of course we Scala folks like tricky things and so we'd tend to say
  "case _ =>" in the second case, but for now you can ignore that as showing off).

So, imagine you are in the second case and actually have a Something.  How do you get at it?

You might think you'd say foo.Some, or Some(foo) or a variation on that theme.  Failing that you might check the documentation on Option or read up on the topic in one of the several fine books on the topic.  Unless you looked someplace I didn't you won't find too much.  Foo.some doesn't exist and most variations of Some(foo) give truely unexpected answers.  For example, try this:

val bla = 4
val foo : Option[Long] = Some(3L)
println(bla > foo)

This results in the pretty confusing error message:

:10: error: overloaded method value > with alternatives:
  (x: Double)Boolean
  (x: Float)Boolean
  (x: Long)Boolean
  (x: Int)Boolean
  (x: Char)Boolean
  (x: Short)Boolean
  (x: Byte)Boolean
 cannot be applied to (Some[Option[Long]])
              bla > Some(foo)
                  ^

So, how do you access the "some" part of an Option?  The "obvious after the fact" answer is with "get".

You can say println(bla > foo.get)

I bet that most people learning Scala have struggled with this or perhaps are still struggling with it.  However, it seems like such a dead simple case that most people won't admit to having been confused by it.

That's my definition of hard because its "too simple to mention".



3 comments:

  1. They might also be needed to perform an interview with officials, submit a resume and go through an English and/or math skills assessment.

    College Automation Software

    ReplyDelete
  2. Brian,

    Calling get on an Option is highly discouraged as it creates a nice opportunity for a null pointer exception to happen. So, I would recommend you always use getOrElse.

    In addition, pattern matching on an Option is not considered the best coding style in Scala.
    Take a look at the Option API page (http://www.scala-lang.org/api/current/index.html#scala.Option) where it's explained at the top how to deal with Options.

    ReplyDelete
  3. After some back and forth we came up with the following as an implementation. The conclusion was that this was good use case for pattern matching on Option but still not for using get.

    def simpleMax(a:Long, b:Long) = if(a >b) a else b

    def max(otherTime: Long, time: Option[Long]): Option[Long] = time match {
    case Some(t) => Some(simpleMax(otherTime, t))
    case None => Some(otherTime)
    }

    ReplyDelete