scala tuple unpacking

ScalaParametersTuples

Scala Problem Overview


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
}

Scala Solutions


Solution 1 - Scala

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)

Solution 2 - Scala

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

Solution 3 - Scala

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)! ;)

Solution 4 - Scala

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)

Solution 5 - Scala

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)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionscoutView Question on Stackoverflow
Solution 1 - ScalaDave GriffithView Answer on Stackoverflow
Solution 2 - ScalaBrendan W. McAdamsView Answer on Stackoverflow
Solution 3 - ScalamissingfaktorView Answer on Stackoverflow
Solution 4 - ScalaxenView Answer on Stackoverflow
Solution 5 - ScalaRejinderiView Answer on Stackoverflow