3

I have a vector of tuples

val l = for {i <- 1 to 5} yield (i,i*2)
Vector((1,2), (2,4), (3,6), (4,8), (5,10))

and I'd like to sum it in the following way:

l.reduce((x,y) => (x._1+y._1, x._2+y._2))
(15,30)

but with use of pattern matching.

I know how to do it if the function gets only one parameter, ie: l.map({case(a,b)=>a+b}), but I can't get it to work with two parameters. this is what I tried to do:

l.reduce({(case(a,b),case(c,d))=>(a+c,b+d)})

but that won't work.

So my question is, how can I unpack 2 tuples that come as a function parameters?

lev
  • 3,986
  • 4
  • 33
  • 46

2 Answers2

6

Just specify type explicitly to help partial functions mechanism:

l.reduce[(Int, Int)]{ case ((a,b), (c, d)) => (a + b, c + d)}

Without [(Int, Int)] scala can't infer correct type for your partial function

P.S. If you're intersesting why you see this error about String regardless what type you're actually using (it's Int in your case):

found   : Any , 
required: String

That's because of implicit "+" for strings in Predef. It's not the only problem with this implicit - you may look at SI-194.

Even without that:

l.reduce{ case ((a,b), (c, d)) => (a, d)}

The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: (?, ?) => ?

scala was unable to infer the type, because it can't infer a type for partial function - may be any supertype of Int: (A1, A1) => A1 expected, where [A1 >: A]

dk14
  • 22,206
  • 4
  • 51
  • 88
  • Nice. Can you explain why is the type required? I would say that compiler knows the type of l. – Rado Buransky Oct 07 '14 at 19:08
  • 1
    The type is specified as [A1 >: A] so scala infers Tuple2[Any, Any] for input, but Tuple2[String, String] for output, because of "+" operation (which is implicit for strings in Predef). Even without + type is uncknown - because pattern matching can't infer type - it don't know which superclass of Int to expect. – dk14 Oct 07 '14 at 19:17
  • Using `fold` and providing the first parameter also works: `nums.fold(0 -> 0){ case ((a, b),(c, d)) => (a + c, b + d) }` – Ben Reich Oct 07 '14 at 19:19
  • Yeah, because you're specifing type semi-explicitly in 0 -> 0, e.g. it's inferred type from first parameter – dk14 Oct 07 '14 at 19:24
2

You wrote something similar to partial function definition. I am not sure if that was your intention. This works:

l.reduce((x,y) => (x, y) match {
  case ((a,b), (c,d)) => (a+c, b+d)
})
Rado Buransky
  • 3,252
  • 18
  • 25