63

In my scala code:

QueueManager.add(getObject)

where getObject is a method that returns an object of type QueueObject.

def getObject : QueuObject = {
    val response = //some response
    return response
}

Is there a way I can check for the response being null, while adding the QueueObject? I know I can do this:

if (getObject != null)
    QueueManager.add(getObject)

But I do not wish to add a level of indentation. Is there an operator that does that inline?

Thanks.

theTuxRacer
  • 13,709
  • 7
  • 42
  • 59

4 Answers4

95

Try to avoid using null in Scala. It's really there only for interoperability with Java. In Scala, use Option for things that might be empty. If you're calling a Java API method that might return null, wrap it in an Option immediately.

def getObject : Option[QueueObject] = {
  // Wrap the Java result in an Option (this will become a Some or a None)
  Option(someJavaObject.getResponse)
}

Note: You don't need to put it in a val or use an explicit return statement in Scala; the result will be the value of the last expression in the block (in fact, since there's only one statement, you don't even need a block).

def getObject : Option[QueueObject] = Option(someJavaObject.getResponse)

Besides what the others have already shown (for example calling foreach on the Option, which might be slightly confusing), you could also call map on it (and ignore the result of the map operation if you don't need it):

getObject map QueueManager.add

This will do nothing if the Option is a None, and call QueueManager.add if it is a Some.

I find using a regular if however clearer and simpler than using any of these "tricks" just to avoid an indentation level. You could also just write it on one line:

if (getObject.isDefined) QueueManager.add(getObject.get)

or, if you want to deal with null instead of using Option:

if (getObject != null) QueueManager.add(getObject)

edit - Ben is right, be careful to not call getObject more than once if it has side-effects; better write it like this:

val result = getObject
if (result.isDefined) QueueManager.add(result.get)

or:

val result = getObject
if (result != null) QueueManager.add(result)
monnef
  • 3,903
  • 5
  • 30
  • 50
Jesper
  • 202,709
  • 46
  • 318
  • 350
13
Option(getObject) foreach (QueueManager add)
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • 2
    Cool, I hadn't realized you could just write `(QueueManager add)` instead of `(QueueManager add _)`. – ebruchez Apr 21 '11 at 16:29
12

If it instead returned Option[QueueObject] you could use a construct like getObject.foreach { QueueManager.add }. You can wrap it right inline with Option(getObject).foreach ... because Option[QueueObject](null) is None.

Ben Jackson
  • 90,079
  • 9
  • 98
  • 150
6

Although I'm sure @Ben Jackson's asnwer with Option(getObject).foreach is the preferred way of doing it, I like to use an AnyRef pimp that allows me to write:

getObject ifNotNull ( QueueManager.add(_) )

I find it reads better.

And, in a more general way, I sometimes write

val returnVal = getObject ifNotNull { obj =>
  returnSomethingFrom(obj)
} otherwise {
  returnSomethingElse
}

... replacing ifNotNull with ifSome if I'm dealing with an Option. I find it clearer than first wrapping in an option and then pattern-matching it.

(For the implementation, see Implementing ifTrue, ifFalse, ifSome, ifNone, etc. in Scala to avoid if(...) and simple pattern matching and the Otherwise0/Otherwise1 classes.)

Community
  • 1
  • 1
Jean-Philippe Pellet
  • 59,296
  • 21
  • 173
  • 234
  • 3
    Ok, but why would you want to make your own version of `if` / `else` (renaming `else` to `otherwise`...). It's an interesting exercise but it doesn't win you anything in practice and might make your code more confusing for others to read. – Jesper Apr 21 '11 at 09:16
  • @Jesper I agree in general — although I find that `getObject ifNotNull ( QueueManager.add(_) )` is less confusing than `Option(getObject).foreach(QueueManager.add(_))`. `foreach` especially would tend to make me think there could be several objects being processed, and I always have to scan back to find out it's actually an `Option`. It would be great if `Option` could have well-named aliases for those methods. – Jean-Philippe Pellet Apr 21 '11 at 10:23
  • Philippe yes, I don't like the trick with `foreach` either, it's indeed a bit misleading when used on an `Option`; the simplest is just to write it with a regular `if`. – Jesper Apr 21 '11 at 22:09