- If we define
Point as a case class, we can turn a (Int, Int) tuple into a Point using Point.tupled.
- We can accept a variable number of arguments using the variable arguments notation
(Int, Int)*.
A function to turn tuples into Points could look like :
case class Point(x: Int, y: Int)
def tupleToPoints(pairs: (Int, Int)*) =
pairs.map(Point.tupled).toArray
scala> tupleToPoints(p1, p2, p3, p4)
res2: Array[Point] = Array(Point(1,2), Point(3,4), Point(33,3), Point(6,67))
If you have a group of points, you can do :
val points = List(p1, p2, p3, p4)
tupleToPoints(points: _*)
Some extra explanation about Point.tupled:
When you call Point(1, 1), you actually call Point.apply(1, 1). If we check the type of Point.apply, we can see it takes two Ints and returns a Point.
scala> Point.apply _
res21: (Int, Int) => Point = <function2>
In your case we have a tuple (Int, Int) which we would like to turn into a Point. The first idea could be pattern matching :
(1, 1) match { case (x, y) => Point(x, y) }
def tupleToPoints(pairs: (Int, Int)*) =
pairs.map { case (x, y) => Point(x, y) }.toArray
// nicer than map(p => Point(p._1, p._2))
But what if we want to use the tuple directly to create a Point using Point.apply, so we don't need this step ? We can use tupled :
scala> (Point.apply _).tupled
res22: ((Int, Int)) => Point = <function1>
We now have a function which takes a tuple (Int, Int) (instead of two Ints) and returns a Point. Because Point is a case class, we can also use Point.tupled which is exactly the same function :
scala> Point.tupled
res23: ((Int, Int)) => Point = <function1>
We can pass this function in our map :
def tupleToPoints(pairs: (Int, Int)*) =
pairs.map(Point.tupled).toArray
// analogous to map(p => Point.tupled(p))