schmmd
schmmd

Reputation: 19478

Functional syntax for nested ifs

sometimes I write code like the following:

val item1 = list.find(_.source.name.equals("foo"))
if (item1.isDefined) doSomething1(item1)
else {
  val item2 = list.find(_.dest.name.equals("bar"))
  if (item2.isDefined) doSomething2(item2)
  else doSomethingElse()
}

Does anyone have a nicer Scala syntax for laying this code out?

Upvotes: 2

Views: 261

Answers (3)

Kevin Wright
Kevin Wright

Reputation: 49705

This should work, though it'll be slightly slower:

val item1 = list find (_.source.name == "foo")
val item2 = list find (_.dest.name == "bar")
item1 map (doSomething1) orElse {
  item2 map (doSomething2)
} getOrElse doSomethingElse()

UPDATE: more efficiently, but not as neat:

val item1 = list find (_.source.name == "foo")
item1 map (doSomething1) orElse {
  val item2 = list find (_.dest.name == "bar")
  item2 map (doSomething2)
} getOrElse doSomethingElse()

Upvotes: 0

Rex Kerr
Rex Kerr

Reputation: 167901

I'd write this as

list.find(_.source.name =="foo").fold(doSomething1) {
  list.find(_.dest.name == "bar").fold(doSomething2)(doSomethingElse)
}

but that is because I have added the method fold to Option like so:

class FoldableOption[A](o: Option[A]) {
  def fold[Z](f: A => Z)(g: => Z) = o.map(f).getOrElse(g)
}
implicit def option_has_folds[A](o: Option[A]) = new FoldableOption(o)

If you don't want to add the fold method, you can also use the map, getOrElse pair:

list.find(_.source.name == "foo").map(doSomething1).getOrElse {
  list.find(_.dest.name == "bar").map(doSomething2).getOrElse(doSomethingElse)
}

which is not much more verbose.

Upvotes: 6

Derek Wyatt
Derek Wyatt

Reputation: 2727

Along with what Kevin said, it's better if these are expressions that return something. I'm going to do the same thing as you but with a different concrete example:

val list = List(1,2,3,4)
val result = list.find(_ == 1).map(
  _ => "Found1").orElse(list.find(_ == 5).map(
    _ => "Found2")).getOrElse("Found3")

However, yours may look better :) But avoid side-effects. Have the if / else chain, or monad chain be an expression that evaluates to something instead of some weird side-effecty kinda thing.

Upvotes: 2

Related Questions