Remedial Scala : Repeated Parameters and Initializing Collections
I only recently began to learn Scala (rooscaloo is coming along nicely, btw). I’m having a great time and the scala-user mailing list has been a great resource for learning more idiomatic ways to express myself in Scala. Every couple of days I ask a dumb question which ends up teaching me a lot about the language. So I figured I’d write about what I learn, even if it’s at a much lower plane of existence than a lot of other Scala commentary that’s out there. Hopefully another neophyte may someday find this informative.
Repeated Parameters
Today’s lesson is about two things that I didn’t initially know were related. First, I wanted to know how to initialize a map with a list of pairs. The Scala Map constructor take a variable list of pairs (a repeated parameter) to initialize the map. For example:
scala> val map = Map((1, 2), (3, 4)) map: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)
But, I have a list of pairs, not a parameter list. So, here’s what I was doing:
val map = Map() ++ listOfPairs
which worked fine. Basically, it takes an empty map and adds the pairs in the list. It smells a little though and I was sure this wasn’t idiomatic. So I asked. The correct answer is the _* operator of course:
scala> val args = List((1, 2), (3, 4)) args: List[(Int, Int)] = List((1,2), (3,4)) scala> val map = Map(args : _*) map: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)
When a parameter is followed by “: _*”, this tells Scala to expand the argument to a variable argument list rather than a single argument. Funny enough, I actually knew this from chapter 8 of the Programming in Scala book, but sometimes I forget things…
So, this explains why all of the Scala collection types take just a repeated parameter list for initialization rather than another collection like the Java collections library.
Turning an Option into a Set
The revelation above led directly to the solution for my other problem. In particular, I wanted a nice way to convert an Option (think of it as a collection with exactly 0 or 1 elements) to a Set. I had this code:
def toSet[T](o : Option[T]) : Set[T] = {
o match {
case Some(some) => Set(some)
case None => Set()
}
}
which works fine, but …
It turns out that Option has a toList method so I can pass it to a repeated parameter list to initialize a collection from an Option:
scala> val s = Set(Some(1).toList : _*) s: scala.collection.immutable.Set[Int] = Set(1)
and:
scala> val s = Set(None.toList : _*) s: scala.collection.immutable.Set[Nothing] = Set()
Pretty cool … Ok, so it isn’t exactly pretty and I stayed with my utility function just for readability, but it’s nice when a language has this kind of consistency where the solution to one problem crops up over and over again.
Remedial, eh?
Thanks for the explanation! And yes, this neophyte find this helpful!
Thanks! Another _ phyte becomes incrementally less neo…