akiva
akiva

Reputation: 2737

How to call .map() on a list of pairs in Scala

I want to call map() on a list of pairs, but I get a type mismatch error.

For example, suppose I want to map a List of pairs of Int to a list of their sums:

scala> val ll=List((1,2),(3,4),(5,6))
ll: List[(Int, Int)] = List((1,2), (3,4), (5,6))

scala> ll.map((x:Int,y:Int)=>x+y)
<console>:9: error: type mismatch;
 found   : (Int, Int) => Int
 required: ((Int, Int)) => ?
              ll.map((x:Int,y:Int)=>x+y)
                                  ^

By the way, when trying to run foreach() I get a very similar error:

scala> ll.foreach((x:Int,y:Int)=>println(x,y))
<console>:9: error: type mismatch;
 found   : (Int, Int) => Unit
 required: ((Int, Int)) => ?
              ll.foreach((x:Int,y:Int)=>println(x,y))
                                  ^

What does the ? sign stand for? What am I missing here?

Upvotes: 28

Views: 27419

Answers (4)

Xavier Guihot
Xavier Guihot

Reputation: 61766

Starting in Scala 3, parameter untupling has been extended, allowing such a syntax:

List((1, 2), (3, 4), (5, 6)).map(_ + _)
// List(3, 7, 11)

where each _ refers in order to the associated tuple part.

Upvotes: 1

Kim Stebel
Kim Stebel

Reputation: 42045

You can use pattern matching to get the elements of the pair.

ll.map{ case (x:Int,y:Int) => x + y }

You don't even need to specify the types:

ll.map{ case (x, y) => x + y }

The same works with foreach of course.

The error message tells you that the compiler expected to find a function of one parameter (a pair of ints) to any type (the question mark) and instead found a function of two parameters, both ints.

Upvotes: 47

Luigi Plinge
Luigi Plinge

Reputation: 51109

You can tuple a function, which means going from one that takes N args to one that takes 1 arg that is an N-tuple. The higher-order function to do this is available on the Function object. This results in nice syntax plus the extra type safety highlighted in the comments to Brian Agnew's answer.

import Function.tupled

ll map tupled(_ + _)

Upvotes: 7

Brian Agnew
Brian Agnew

Reputation: 272417

You can use:

ll.map(x => x._1 + x._2)

where x stands for the tuple itself, or

ll.map(x:(Int,Int) => x._1 + x._2)

if you want to declare the types explicitly.

Upvotes: 20

Related Questions