Why is it better to use case in args function for pattern matching in map function

Scala cheatsheet say "use argument in function arguments for pattern matching". as such

GOOD (xs zip ys) map { case (x,y) => x*y }
BAD (xs zip ys) map( (x,y) => x*y )

      

Why is the former better?

+3


source to share


3 answers


(x, y) => x * y

is syntactic sugar for the following (I'm assuming we're talking about integers):

new Function2[Int, Int, Int] {
  def apply(x: Int, y: Int): Int = x * y
}

      

map

on collections takes a A => B

(which desugars up to Function1[A, B]

), which is completely different from Function2

. So one good reason not to use the latest version in your example is that the compiler will not accept it.



In cases where you have a method that actually accepts Function2

, you can use either:

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

scala> pair.zipped.map { (x, y) => x * y }
res0: List[Int] = List(4, 10, 18)

scala> pair.zipped.map { case (x, y) => x * y }
res1: List[Int] = List(4, 10, 18)

      

The version case

works because of the way the compiler supports pattern matching in the literal function syntax for Function2

. In general, I personally prefer the syntax for (x, y) => x * y

when it works (i.e. when your method expects Function2

and you don't need to do any other pattern matching).

+5


source


Well, the latter just won't work.

scala> val xs = List(1, 2, 3)
xs: List[Int] = List(1, 2, 3)

scala> val ys = List(4, 5, 6)
ys: List[Int] = List(4, 5, 6)

scala> (xs zip ys).map((x,y) => x*y)
<console>:10: error: missing parameter type
Note: The expected type requires a one-argument function accepting a 2-Tuple.
      Consider a pattern matching anonymous function, `{ case (x, y) =>  ... }`
              (xs zip ys).map((x,y) => x*y)
                               ^
<console>:10: error: missing parameter type
              (xs zip ys).map((x,y) => x*y)
                                 ^

scala> (xs zip ys).map { case (x,y) => x*y }
res0: List[Int] = List(4, 10, 18)

      



As an alternative

import Function.tupled
(xs zip ys) map tupled { (x,y) => x*y }

      

+1


source


In pattern matching, you explicitly specify the form (type) of the input parameter to match (a function with one argument that takes a tuple-2); in the second case (no pattern matching), you need to specify the type explicitly (since it has the same form as a function with two arguments). You can see this by simply typing it into the REPL (scala 2.11.6):

scala> val xs = List(1,2,3,4)
xs: List[Int] = List(1, 2, 3, 4)
scala> val ys = List(1,2,3,4)
ys: List[Int] = List(1, 2, 3, 4)
scala> (xs zip ys) map { case (x,y) => x*y }
res0: List[Int] = List(1, 4, 9, 16)
scala> (xs zip ys) map ((x,y) => x*y)
<console>:10: error: missing parameter type
Note: The expected type requires a one-argument function accepting
a 2-Tuple.
Consider a pattern matching anonymous function, `{ case (x, y) =>  }`
          (xs zip ys) map ((x,y) => x*y)
                            ^
<console>:10: error: missing parameter type
          (xs zip ys) map ((x,y) => x*y)

      

-1


source







All Articles