Question

Is it possible to write a generalised orElse method from Option that takes a variable number of arguments? That is, instead of:

lazy val o1 = { println("foo"); None }
lazy val o2 = { println("bar"); Some("bar") }
lazy val o3 = { println("baz"); Some("baz") } 
// ...
o1 orElse o2 orElse o3 // orElse ...

You could use:

orElse(o1, o2, o3) //, ...
Was it helpful?

Solution

According to the The Scala Language Specification (4.6 Function Declarations and Definitions) you cannot define varargs by-name parameters:

ParamType ::= Type
| ‘=>’ Type
| Type ‘*’

scala> def orElse(x : (=> String)*)
<console>:1: error: no by-name parameter type allowed here
       def orElse(x : (=> String)*)

You could replace the lazy arg with function and an implicit type conversion:

def orElse[T](x : (()=> Option[T])*) : Option[T] = 
    if(x.isEmpty) None else x.first.apply.orElse(orElse((x drop 1) :_*))
implicit def anyToFun0[T](t : => T) : (() => T) = () => t
orElse(o1, o2, o3)

OTHER TIPS

I found the question a bit late :). One possibility is to wrap => A into a helper class together with a helper function to simplify its creation:

import scala.language.implicitConversions

class Helper[+A](value: => A) extends Function0[A] {
  override def apply(): A = value;
}
object Helper {
  def unapply[A](h: Helper[A]): Option[A] = Some(h());
}
implicit def toHelper[A](body: => A) = new Helper(body);

The extractor isn't required, it just allows easy matching on the helper. Then we can write

def orElse[A](xs: Helper[Option[A]]*): Option[A] =
  xs.collectFirst[A]({
    case Helper(Some(r)) => r;
  })

lazy val o1 = { println("foo"); None }
lazy val o2 = { println("bar"); Some("bar") }
lazy val o3 = { println("baz"); Some("baz") }

orElse(o1, o2, o3) //, ...

This is just a simplified solution, a more realistic one would be

def orElse[A](x: Option[A], xs: Helper[Option[A]]*): Option[A]

with a more efficient implementation.


There already is a class similar to Helper in Scalaz, called Name with implementation Need that ensures that the body is evaluated at most once. So with Scalaz, it could be implemented as

import scala.language.implicitConversions
import scalaz._
import scalaz.Scalaz._

implicit def toNeed[A](body: => A): Name[A] = Need(body);

def orElse[A](xs: Name[Option[A]]*): Option[A] =
  xs.collectFirst[A]({
    case Name(Some(r)) => r;
  })

lazy val o1 = { println("foo"); None }
lazy val o2 = { println("bar"); Some("bar") }
lazy val o3 = { println("baz"); Some("baz") }

orElse(o1, o2, o3) //, ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top