Jus12 Jus12 - 1 month ago 8
Scala Question

Can we have an array of by-name-parameter functions?

In Scala we have a by-name-parameters where we can write

def foo[T](f: => T):T = {
f // invokes f
// use as:

I now want to do the same with an array of methods, that is I want to use them as:

def foo[T](f:Array[ => T]):T = { // does not work
f(0) // invokes f(0) // does not work
foo(println("hi"), println("hello")) // does not work

Is there any way to do what I want? The best I have come up with is:

def foo[T](f:() => T *):T = {
f(0)() // invokes f(0)
// use as:
foo(() => println("hi"), () => println("hello"))


def foo[T](f:Array[() => T]):T = {
f(0)() // invokes f(0)
// use as:
foo(Array(() => println("hi"), () => println("hello")))

EDIT: The proposed SIP-24 is not very useful as pointed out by Seth Tisue in a comment to this answer.

An example where this will be problematic is the following code of a utility function

type unitToT[T] = ()=>T
def trycatch[T](list:unitToT[T] *):T = list.size match {
case i if i > 1 =>
try list.head()
catch { case t:Any => trycatch(list.tail: _*) }
case 1 => list(0)()
case _ => throw new Exception("call list must be non-empty")

takes a list of methods of type
and applies each element successively until it succeeds or the end is reached.

Now suppose I have two methods:

def getYahooRate(currencyA:String, currencyB:String):Double = ???


def getGoogleRate(currencyA:String, currencyB:String):Double = ???

that convert one unit of
and output

I use

val usdEuroRate = trycatch(() => getYahooRate("USD", "EUR"),
() => getGoogleRate("USD", "EUR"))

I would have preferred:

val usdEuroRate = trycatch(getYahooRate("USD", "EUR"),
getGoogleRate("USD", "EUR")) // does not work

In the example above, I would like
getGoogleRate("USD", "EUR")
to be invoked only if
getYahooRate("USD", "EUR")
throws an exception. This is not the intended behavior of SIP-24.


As of Scala 2.11.7, the answer is no. However, there is SIP-24, so in some future version your f: => T* version may be possible.