- 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))