views:

158

answers:

1

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) //, ...
+4  A: 

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)
Thomas Jung
I tried this at the repl, but unfortunately it appears to force all three arguments.
Matt R
You're right the implicit type conversion forced the evaluation. I fixed the code.
Thomas Jung