Search code examples
scalavariadic-functionslazy-evaluation

How to write a lazy, variable argument version of "orElse"


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) //, ...

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)