101

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
}
scout
  • 2,336
  • 4
  • 21
  • 22
  • 13
    What if foo happens to be the constructor of some class? – scout Aug 25 '10 at 16:26
  • Possible duplicate of [How to apply a function to a tuple?](http://stackoverflow.com/questions/1987820/how-to-apply-a-function-to-a-tuple) – Suma Jan 06 '16 at 16:17

5 Answers5

113

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
  • 20,435
  • 3
  • 55
  • 76
  • 3
    Would it not be cleaner if Scala just thought of arguments as Tuples to start with? – Henry Story Feb 19 '12 at 21:10
  • 12
    Yes, it would be a lot cleaner if Scala would unify it's handling of tuples and argument lists. From what I've heard, there are a lot of non-obvious edge-cases that would need careful handling to make that happen. As far as I know, unification of tuples and argument lists is not on the Scala roadmap at this time. – Dave Griffith Feb 19 '12 at 21:29
  • 2
    Just to add, if foo is the factory method of the companion object, one could use (Foo.apply _).tupled(getParams) – RAbraham Aug 13 '13 at 00:55
59

@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 = <function1>

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>

ceyko
  • 4,822
  • 1
  • 18
  • 23
Brendan W. McAdams
  • 9,379
  • 3
  • 41
  • 31
21

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
  • 90,905
  • 62
  • 285
  • 365
  • 3
    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 Aug 26 '10 at 00:15
4

I appreciate some of the other answers which were closer to what you asked for, but I found it easier for a current project to add another function which converts tuple parameters into the split parameters:

def originalFunc(a: A, b: B): C = ...
def wrapperFunc(ab: (A, B)): C = (originalFunc _).tupled(ab)
xen
  • 133
  • 6
1

Now, you can implement foo and make it take a param of the Tuple2 class like so.

def foo(t: Tuple2[Int, Int]) = {
  println("Hello " + t._1 + t._2)
  "Makes no sense but ok!"
}

def getParams = {
  //Some calculations
  val a = 1;
  val b = 2;
  (a, b) //where a & b are Int
}

// So you can do this!
foo(getParams)
// With that said, you can also do this!
foo(1, 3)
Rejinderi
  • 11,694
  • 2
  • 31
  • 40