How to pass a tuple argument the best way?

21,860

Solution 1

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

Solution 2

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?

Solution 3

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.

Share:
21,860
John Threepwood
Author by

John Threepwood

Primary interests: Logic, Java/C#, C/C++. If you wish to get in contact, please email me: firstname.lastname at GMAIL

Updated on July 09, 2022

Comments

  • John Threepwood
    John Threepwood almost 2 years

    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 ?

  • John Threepwood
    John Threepwood almost 12 years
    Thank you. I agree, this is more readable. I will keep that trick in mind. But the extra value annoys me a bit. I would like to pass it through without saving the result to an extra value. But still thank you for this hint !
  • John Threepwood
    John Threepwood almost 12 years
    Thank you, this is what I was looking for. That will do the trick for me. Extra question: You mentioned out, that there is a difference between a method and a function - what is the difference ? I would like to know more about it. Can you give me some references/links where I can read more about it ?
  • Tomasz Nurkiewicz
    Tomasz Nurkiewicz almost 12 years
    @JohnThreepwood: methods in Scala translate to methods in Java. Functions in Scala translate to objects. In Scala this is mostly transparent (search for "eta-expansion"), but sometimes the syntax is slightly different. This article is very comprehensive.
  • John Threepwood
    John Threepwood almost 12 years
    Thank you for pointing out this alternative. But why is a tuple as return value a sign of not to care about performance ? But yes, your are right, in my program the performance does not matter that much.
  • Rex Kerr
    Rex Kerr almost 12 years
    @JohnThreepwood - You have to create an object to return a tuple. If whatever you're doing is expensive compared to object creation, then it is probably also expensive compared to two object creations (which is what you get with bar _ and .tupled). If what you're doing is cheap compared to object creation, why did you create an object? You should have passed in an object with vars that you could set. (The latter approach is something you should do rarely if at all--object creation is fairly cheap.)
  • John Threepwood
    John Threepwood almost 12 years
    Thank you for clearification. The explaination makes sense, I will keep it in mind.
  • matanster
    matanster over 8 years
    It is rather disappointing that this works only for methods and certainly unpleasing that scala provides such a hairy surface to its api. There's nothing making us smarter nor productive by bypassing these kinds of language limitations...