John Threepwood
John Threepwood

Reputation: 16143

How to pass a tuple argument the best way?

How to pass a tuple argument the best way ?

Example:

def foo(...): (Int, Int) = ...

def bar(a: Int, b: Int) = ...

Now I would like to pass the output of foo to bar. This can be achieved with:

val fooResult = foo(...)
bar(fooResult._1, fooResult._2)

This approach looks a bit ugly, especially when we deal with a n-tuple with n > 2. Also we have to store the result of foo in an extra value, because otherwise foo has to be executed more than once using bar(foo._1, foo._2).

Is there a better way to pass through the tuple as argument ?

Upvotes: 40

Views: 25838

Answers (3)

Rex Kerr
Rex Kerr

Reputation: 167891

It is worth also knowing about

foo(...) match { case (a,b) => bar(a,b) }

as an alternative that doesn't require you to explicitly create a temporary fooResult. It's a good compromise when speed and lack of clutter are both important. You can create a function with bar _ and then convert it to take a single tuple argument with .tupled, but this creates a two new function objects each time you call the pair; you could store the result, but that could clutter your code unnecessarily.

For everyday use (i.e. this is not the performance-limiting part of your code), you can just

(bar _).tupled(foo(...))

in line. Sure, you create two extra function objects, but you most likely just created the tuple also, so you don't care that much, right?

Upvotes: 10

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340723

There is a special tupled method available for every function:

val bar2 = (bar _).tupled  // or Function.tupled(bar _)

bar2 takes a tuple of (Int, Int) (same as bar arguments). Now you can say:

bar2(foo())

If your methods were actually functions (notice the val keyword) the syntax is much more pleasant:

val bar = (a: Int, b: Int) => //...
bar.tupled(foo())

See also

Upvotes: 58

dhg
dhg

Reputation: 52681

Using tupled, as @Tomasz mentions, is a good approach.

You could also extract the tuple returned from foo during assignment:

val (x, y) = foo(5)
bar(x, y)

This has the benefit of cleaner code (no _1 and _2), and lets you assign descriptive names for x and y, making your code easier to read.

Upvotes: 9

Related Questions