Take the 2-minute tour ×

I have this Java class in a Jar file included as a dependency of an Scala program (like the Axis jar):

class MyClass {
    private String[] someStrings;
    public String[] getSomeStrings() { return someStrings; }

In my Scala program I have a Java API that return an instance of MyClass instance of MyClass to my program in Scala:

val myInstance = JavaAPI.getInstanceOfMyClass()

Then I try to use the someStrings array in my Scala program but it's null (let say that it wasn't properly initialized)

for(str <- myInstance.getSomeStrings()) ...

So this throws a NullPointerException.

I've found that in order to use it in the for comprehension I can wrap it into an Option so that it handles the NPE properly.

for(str <- Option[Array[String]](myInstance.getSomeStrings).getOrElse(Array[String]())

But that doesn't look OK to me.

Is there a way to create like an implicit method that takes that value even if it's null and wrap it into the Option, like:

implicit def wrapNull(a: Null): Option[Nothing] = None
implicit def wrapArray(a: Array[String]): Option[Array[String]] = Some(a)

So that when I do:

for(str <- myInstance.getSomeStrings())

I don't get the NPE

Thanks in advance!

share|improve this question
You should have specified the "chained nullable partial results" requirement in the question. –  Daniel C. Sobral Apr 12 '12 at 22:46

3 Answers 3

up vote 3 down vote accepted

I don't think your version with getOrElse is that bad (you can make it a little shorter by removing the [Array[String]] after Option, since that can be inferred). If you want something even more concise, the following works:

for (str <- Option(myInstance.getSomeStrings).flatten) ...

You could also use the fact that Option has a foreach:

for {
  strings <- Option(myInstance.getSomeStrings)
  str <- strings
} ...

Note that you can't use yield here, for the reason that drexin highlights in a comment below.

Or you could pimp MyClass:

implicit def withNullWrapper(c: MyClass) = new {
  def getSomeStringsOrNot() = Option(c.getSomeStrings).getOrElse(Array[String]())

for (str <- myInstance.getSomeStringsOrNot) ...
share|improve this answer
Your flatMap example will not work, because it does not follow the monad laws. strings is an Array[String] and therefore flatMap can't be used here. –  drexin Apr 12 '12 at 22:06
You're right—but the same for-comprehension syntax will work if you don't use yield. –  Travis Brown Apr 12 '12 at 22:12
Yes, because it will be translated to a nested foreach. But then you rely on side effects which should be avoided. –  drexin Apr 12 '12 at 22:13


A mapas well as a flatMap always have to return the same type, on which they are called. If you have a List, you will always get a List back from map. The same is true for an Option. If you try to mix 2 types in a flatMap, this will most likely not work. What should

Some(Array(1,2)).flatMap { x => 
  x.map { _ * 2 }

return? Some(2,4) is not possible. So you get a type error. For this reason you have to do a nested map { map } instead of flatMap { map }.

In your case it would work like this:

case class A(b: B)
case class B(c: String)

val result = for(as <- Option(Array(A(B("foo")), A(B("bar"))))) yield {
  for(a <- as; b <- Option(a.b); c <- Option(b.c)) yield {

The first for takes an Option[Array[A]] and returns an Option[Array[String]]. The nested for takes an Array[A] and returns an Array[String]. They both satisfy the monad laws. At the end you can safely call getOrElse on result to unwrap the value if you want to.


You could just do

val result = Option(myInstance.getSomeStrings).map { x =>
  x.map { y =>
    // do stuff with strings


val result = for(x <- Option(myInstance.getSomeStrings)) yield {
  x.map { y =>
    // do stuff with strings

You don't need to write the types because of the type inference and you don't need getOrElse, because the map will not be executed for None. You can then simply do a getOrElse on result, if you need to unwrap the value.

share|improve this answer
Thanks for this. I should explained my self better. The problem is when you have "nested?" assignments? in the for like for(a <- As; b <- a.b; c <- b.c). How is this done with the option? a, b and c can be null. for(a <- Option(As); b <- Option(a.flatten).get.b and so on? Thanks a lot. –  jmdev Apr 12 '12 at 21:57
updated my answer –  drexin Apr 12 '12 at 22:35

Simple rule: where there's a null, make it an Option. So:

for {
  array <- Option(myInstance.getSomeStrings)
  element <- array
  thingy <- Option(element.method)
} yield thingy

Only that won't work. Because of the array, it will return multiple elements, but because the first generator is an Option, it will return an Option. These two elements are adverse: you can't return an Option of multiple elements.

The simplest alternative to fix the problem is to convert the Option into an iterator or a collection (according to your taste). Like this:

for {
  array <- Option(myInstance.getSomeStrings).toSeq
  element <- array
  thingy <- Option(element.method)
} yield thingy

Note that the second Option need not be touched: the one that caused the problem was the one as the first generator. Option anywhere other than the first generator is not a problem.

share|improve this answer

Your Answer


