views:

160

answers:

3

I know this question has come up many times in different ways. But it is still not clear to me. Is there a way to achieve the following.

def foo(a:Int, b:Int) = {}

foo(a,b) //right way to invoke foo

foo(getParams) // is there a way to get this working without explicitly unpacking the tuple??

def getParams = {
   //Some calculations
   (a,b)  //where a & b are Int
}
+7  A: 

It's a two step procedure. First turn foo into a function, then call tupled on it to make it a function of a tuple.

(foo _).tupled(getParams)
Dave Griffith
+2  A: 

Function.tupled(foo _)(getParams) or the one suggested by Dave.

EDIT:

To respond to your comment:

What if foo happens to be the constructor of some class?

In that case, this trick won't work.

You can write a factory method in the companion object of your class and then obtain the tupled version of its apply method using one of the aforementioned techniques.

scala> class Person(firstName: String, lastName: String) {
     |   override def toString = firstName + " " + lastName
     | }
defined class Person

scala> object Person {
     |   def apply(firstName: String, lastName: String) = new Person(firstName, lastName)
     | }
defined module Person

scala> (Person.apply _).tupled(("Rahul", "G"))
res17: Person = Rahul G

With case classes you get a companion object with an apply method for free, and thus this technique is more convenient to use with case classes.

scala> case class Person(firstName: String, lastName: String)
defined class Person

scala> Person.tupled(("Rahul", "G"))
res18: Person = Person(Rahul,G)

I know that's a lot of code duplication but alas... we don't have macros (yet)! ;)

missingfaktor
In the last example here, you could shave off a bit... Companion objects for case classes always extend the appropriate FunctionN trait. So the last line could be``Person.tupled(("Rahul", "G"))``It's handy to do this in hand-written companion objects too.
David Winslow
@David: Edited, thanks. :-)
missingfaktor
+6  A: 

@dave-griffith is dead on.

You can also call:

Function.tupled(foo _)

If you want to wander into "way more information than I asked for" territory, there are also methods built into partially applied functions (and on Function) for currying. A few input/output examples:

scala> def foo(x: Int, y: Double) = x * y
foo: (x: Int,y: Double)Double

scala> foo _
res0: (Int, Double) => Double = <function2>

scala> foo _ tupled
res1: ((Int, Double)) => Double = <function1>

scala> foo _ curried
res2: (Int) => (Double) => Double = <function1>

scala> Function.tupled(foo _)
res3: ((Int, Double)) => Double = <function1>

// Function.curried is deprecated
scala> Function.curried(foo _)
warning: there were deprecation warnings; re-run with -deprecation for details
res6: (Int) => (Double) => Double = <function1>

Wherein the curried version is invoked with multiple argument lists: scala> val c = foo _ curried c: (Int) => (Double) => Double =

scala> c(5)
res13: (Double) => Double = <function1>

scala> c(5)(10)
res14: Double = 50.0

Finally, you can also uncurry/untuple if needed. Function has builtins for this:

scala> val f = foo _ tupled
f: ((Int, Double)) => Double = <function1>

scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>

scala> Function.uncurried(c)
res9: (Int, Double) => Double = <function2>

scala> Function.untupled(f)
res12: (Int, Double) => Double = <function2>
Brendan W. McAdams