58

This should be an easy one. How do I apply a function to a tuple in Scala? Viz:

scala> def f (i : Int, j : Int) = i + j
f: (Int,Int)Int

scala> val p = (3,4)
p: (Int, Int) = (3,4)

scala> f p
:6: error: missing arguments for method f in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
       f p
       ^

scala> f _ p
:6: error: value p is not a member of (Int, Int) => Int
       f _ p
           ^

scala> (f _) p
:6: error: value p is not a member of (Int, Int) => Int
       (f _) p
             ^

scala> f(p)
:7: error: wrong number of arguments for method f: (Int,Int)Int
       f(p)
       ^

scala> grr!

Many thanks in advance.

Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
John Clements
  • 16,895
  • 3
  • 37
  • 52

5 Answers5

79

In Scala 2.8 and newer:

scala> def f (i : Int, j : Int) = i + j
f: (i: Int,j: Int)Int

// Note the underscore after the f
scala> val ff = f _
ff: (Int, Int) => Int = <function2>

scala> val fft = ff.tupled
fft: ((Int, Int)) => Int = <function1>

In Scala 2.7:

scala> def f (i : Int, j : Int) = i + j
f: (Int,Int)Int

// Note the underscore after the f
scala> val ff = f _
ff: (Int, Int) => Int = <function>

scala> val fft = Function.tupled(ff)
fft: ((Int, Int)) => Int = <function>
fresskoma
  • 25,481
  • 10
  • 85
  • 128
Randall Schulz
  • 26,420
  • 4
  • 61
  • 81
  • 1
    interesting to note, scala (2.11.0 here) will bring your untupled params up to a tuple if you do: `fft.apply(1,2)` – ThaDon Sep 11 '14 at 12:57
  • Good to know you can do this, but this seems not much shorter than just using `function(tup._1,tup._2)` in the first place – Allen Wang Oct 10 '16 at 23:40
  • 3
    @AllenWang I think the important point is that `tupled` can be used for any arity. Good for maintainability. – Ohashi Nov 01 '16 at 02:42
18

Following up on the other answer, one could write (tested with 2.11.4):

scala> def f (i: Int, j: Int) = i + j
f: (i: Int, j: Int)Int

scala> val ff = f _
ff: (Int, Int) => Int = <function2>

scala> val p = (3,4)
p: (Int, Int) = (3,4)

scala> ff.tupled(p)
res0: Int = 7

See def tupled: ((T1, T2)) ⇒ R:

Creates a tupled version of this function: instead of 2 arguments, it accepts a single scala.Tuple2 argument.

Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
7

Scala 2.13

def f (i : Int, j : Int) = i + j

import scala.util.chaining._
(3,4).pipe((f _).tupled)   //res0: Int = 7
jwvh
  • 50,871
  • 7
  • 38
  • 64
1
scala> def f (i: Int, j: Int) = i + j
f: (i: Int, j: Int)Int
scala> val p = (3,4)
p: (Int, Int) = (3,4)
scala> val ft = (f _).tupled
ft: ((Int, Int)) => Int = <function1>
scala> ft apply(p)
res0: Int = 7
Misa Lazovic
  • 2,805
  • 10
  • 32
  • 38
Val K
  • 105
  • 8
1

In Scala 3, you can use TupledFunction:

For a single use, you can do

summon[TupledFunction[(Int, Int) => Int, ((Int, Int)) => Int]].tupled(f)((2, 3))

To make it easier to use, you can use an extension (copied from Dotty's own documentation)

extension [F, T <: Tuple, R](f: F)(using tf: TupledFunction[F, T => R])
  def tupled(t: T): R = tf.tupled(f)(t)

And then you can do f.tupled((2, 3)) to get 5.

user
  • 7,435
  • 3
  • 14
  • 44