Jus12 Jus12 - 3 days ago 5
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:
foo(println("hello"))


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"))


or

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
trycatch
:

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")
}


Here
trycatch
takes a list of methods of type
()=>T
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 = ???


and

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


that convert one unit of
currencyA
to
currencyB
and output
Double
.

I use
trycatch
as:

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.

Answer

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.

Comments