I keep stumpling upon this problem and it is annoying (Scala 2.13.4).
case class Coord(x: Int, y: Int)
val data: List[(Int, Int)] = List( (1,2), (3,4) )
data.map{ (x,y) =>
Coord(x,y)
}
gives me this error:
found : (Int, Int) => Coord
required: ((Int, Int)) => Coord
Which I can resolve by adding the "case" keyword
data.map{ case (x,y) =>
Coord(x,y)
}
My question ist when is it mandatory to use the 'case' keyword (here in this specific case and in general). The compiler should already know that it will get a tuple of Int. It seems that most of the time it is not needed. Are there special rules for tuples because they also use parens?
CodePudding user response:
It's never mandatory to use case
in a function literal.
{ (x, y) => ??? }
defines a function of two arguments, akin to what you'd get from code like
object Foo extends Function2[A, B, C] {
def apply[A, B, C](x: A, y: B): C = ???
}
When passing a tuple, the tuple is passed as a single argument and it then needs to be destructured inside the function. The following are all equivalent ways of destructuring the tuple
{ tuple =>
val (x, y) = tuple
???
}
{ tuple =>
tuple match {
case (x, y) => ???
}
}
{ case (x, y) => ??? }
Note that if you have a function value which takes more than 1 argument, that value has a tupled
method which converts a function of n arguments into a function taking a single tuple of n components.
val f = { (x: Int, y: Int) => Coord(x, y) }
// alternatively:
// val f: (Int, Int) => Coord = Coord.apply
val coordinatePairs = List( (1, 2), (3, 4) )
// alternatively:
// val coordinatePairs = List(1 -> 2, 3 -> 4)
coordinatePairs.map(f.tupled)
CodePudding user response:
data.map{ case (x,y) =>
Coord(x,y)
}
is equivalent to
data.map { tuple =>
tuple match {
case (x, y) => Coord(x,y)
}
}
Its called pattern matching anonymous function.