# Tuples are Different to Function Arguments in Scala

In Scala Tuples and function arguments look similar but they can’t be used interchangeably.

A Tuple of two Ints can be defined as:

```
> val t2 = (2, 4)
scala: (Int, Int) = (2,4) t2
```

Given a simple **sum** method that takes in two Ints:

`def sum(n1: Int, n2: Int) = n1 + n2`

you might think that you could simply pass in your tuple **t2** to invoke the **sum** method:

```
> sum(t2)
scala<console>:15: error: not enough arguments for method sum: (n1: Int, n2: Int)Int.
.
Unspecified value parameter n2sum(t2)
```

Unfortunately this does not work as you can’t simply replace an argument list with a similarly-sized tuple. **t2** is taken as the first argument **n1**, hence the error indicating that **n2** has not been supplied.

One way to get this to work is to do the following:

```
> sum _ tupled t2
scala: Int = 6 res0
```

Let’s break that incantation down step-by-step to make it more digestible.

- Convert the
**sum**method into a Function:

```
> val f1 = sum _
scala: (Int, Int) => Int = $$Lambda$1447/998900406@31452c9 f1
```

- Convert the function into its tupled variant:

```
> val f2 = f1.tupled
scala: ((Int, Int)) => Int = scala.Function2$$Lambda$227/234698513@3f891cfe f2
```

Tupling the **sum** function is merely going from `(Int, Int) => Int`

to `((Int, Int)) => Int`

. Notice the extra parenthesis around the arguments.

- Apply the tupled function to the tupled input
**t2**:

```
> f2(t2)
scala: Int = 6 res21
```

Looking back that does look very difficult but it’s not very intuitive.

### Using Underscores with Currying

I had a similar problem recently where I had a **contains** method defined as:

```
def contains[A](values: List[A], value: A, pred: A => A => Boolean): Boolean = {
.exists(pred(value))
values}
```

And a List **l1** defined as:

`val l1 = List(1, 2, 3)`

I tried to call the **contains** method using underscores for the values of the **pred** parameter and got the following error:

```
> contains[Int](l1, 3, _ == _)
scala<console>:17: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$eq$eq(x$2))
[Int](l1, 3, _ == _)
contains^
<console>:17: error: missing parameter type for expanded function ((x$1: <error>, x$2: <error>) => x$1.$eq$eq(x$2))
[Int](l1, 3, _ == _) contains
```

You can use underscores to represent positional arguments in an argument list where you don’t need to bind it to a name. So why did this fail?

I can get the **contains** method to work with:

```
> contains[Int](l1, 3, x => y => x == y)
scala: Boolean = true res24
```

Conversely, why did this work?

Another interesting variant is if I change the definition of **contains** to **contains2** that takes in an uncurried **pred** function:

```
def contains2[A](values: List[A], value: A, pred: (A, A) => Boolean): Boolean = {
.exists(pred(value, _))
values}
```

I can invoke it with the underscore syntax:

```
> contains2[Int](l1, 3, _ == _)
scala: Boolean = true res59
```

One of the main reasons for using a curried version of **pred** was that I could partially apply it with the exists method on List without having to use underscores to convert the method to a function. I can still achieve the same result by currying **pred** where it is applied:

```
def contains3[A](values: List[A], value: A, pred: (A, A) => Boolean): Boolean = {
.exists(pred.curried(value))
values}
```

The reason I couldn’t use underscores to represent the parameters of the **contains** method is that the curried function **pred**, represents two argument lists; One that takes an `A`

and returns another function that takes another `A`

and returns a Boolean:

`(A) => (A => Boolean)`

Underscores can only used to represent positional arguments of a single argument list, since we have two in the curried variation of **pred** in **contains** we can’t use it.

### Changing the shape of the Input Function

If I define a uncurried function **isEqual** as:

`def isEqual[A](a1: A, a2: A): Boolean = a1 == a2`

I can call **contains2** as:

```
> contains2[Int](l1, 3, isEqual)
scala: Boolean = true res32
```

If I define an **isEqual2** as:

`def isEqual2[A]: A => A => Boolean = a1 => a2 => a1 == a2`

I can call **contains** as:

```
> contains[Int](l1, 3, isEqual2)
scala: Boolean = true res33
```

But if I try to call **contains2** with **isEqual2** we get:

```
> contains2[Int](l1, 3, isEqual2[Int])
scala<console>:18: error: type mismatch;
: Int => (Int => Boolean)
found : (Int, Int) => Boolean
required[Int](l1, 3, isEqual2[Int]) contains2
```

And we can fix that by uncurrying **isEqual2**:

```
> contains2(l1, 3, Function.uncurried(isEqual2))
scala: Boolean = true res65
```

If we define **isEqual3** with a Tuple2 as:

`def isEqual3[A]: Tuple2[A, A] => Boolean = t => t._1 == t._2`

And we try to invoke **contains2** with **isEqual3** we get:

```
> contains2(l1, 3, isEqual3[Int])
scala<console>:15: error: type mismatch;
: ((Int, Int)) => Boolean
found : (?, ?) => Boolean
requiredcontains2(l1, 3, isEqual3[Int])
```

And we can easily fix that by untupling the parameters to **isEqual3**:

```
> contains2(l1, 3, Function.untupled(isEqual3))
scala: Boolean = true res69
```

### Case Class Constructors

And one last example invoking a constructor of a case class:

```
> case class Person(name: String, age: Int)
scalaclass Person
defined
> val nameAge = ("Katz", 20)
scala: (String, Int) = (Katz,20)
nameAge
> val pc = Person.apply _
scala: (String, Int) => Person = $$Lambda$1565/1849401610@5417f849 pc
```

If I try to invoke **pc** with **nameAge** I get an error as expected:

```
> pc nameAge
scala<console>:13: error: value nameAge is not a member of (String, Int) => Person
pc nameAge
```

And we can solve that by tupling the constructor:

```
> pc tupled nameAge
scala: Person = Person(Katz,20) res21
```

Or more succinctly:

```
> Person.tupled(nameAge)
scala: Person = Person(Katz,20) res22
```

Hopefully this has given you some insight into the various ways to invoke functions that takes tuples, curried arguments or uncurried variants.

Some references: