Scala snippets 2: List symbol magic
The following other snippets are also available:
In scala every symbol can be a function, so overloading operators (which isn’t really overloading, since operators are already methods) is very easy and is something which you see in many libraries. In this snippet we’ll just explore a couple of the overloaded methods that make working with lists much easiers.
So lets get started and look at the ++ operator. First, like we always do, lets create a list.
scala> val list = 0 until 10 toList list: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) scala> val list2 = 10 to 0 by -1 toList list2: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
And just walk through the operators from here: http://www.scala-lang.org/api/2.11.1/index.html#scala.collection.immutab…
The first operator we’ll look at is ++. With this operator we can add two lists together, and return a new one:
scala> val list3 = list ++ list2 list3: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) scala> val list3 = list2 ++ list list3: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
Note that you don’t have to add the same types. Scala will automatically select the most relevant superclass.
scala> val list1 = 0 to 10 toList list1: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> val list2 = 10 to 0 by -1 toList list2: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) scala> val list3 = list1.asInstanceOf[List[Double]] list3: List[Double] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> list3 ++ list2 res4: List[AnyVal] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
As you can see AnyVal is the most common supertype of both Int and Double so that one gets selected.
Now that we’ve seen the ++ operator lets look at one almost the same the ++: operator.With this operator we have the same semantics as ++ but this time the type of the result is determined by the right operand instead of the left one:
scala> vector1 res14: Vector[Int] = Vector(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20) scala> list1 res15: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> vector1 ++ list1 res16: scala.collection.immutable.Vector[Int] = Vector(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> vector1 ++: list1 res17: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
On to the next two operators :+ and +:. With these two operators we can append and prepend an element to a list:
scala> 999 +: list1 res27: List[Int] = List(999, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> list1 :+ 999 res28: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 999)
Simple right? Note that the : is always on the side of the list (target). The same goes for the ++: operator we saw earlier.
What more do we have? :: and :::. Both these operators add something to the beginning of a list. The :: operator adds a single element, and the ::: operator add a complete list. So basically they are the same as the +: and the ++ operator. The main change is that ++ and +: can be used with Traversable and ::: and :: can only be used with a list.
scala> 11 +: list1 res38: List[Int] = List(11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> list1 res39: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> 11 +: list1 res40: List[Int] = List(11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> list2 res41: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) scala> list1 ::: list2 res43: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
And then we’ve pretty much covered all except :\ and :/. These functions allow you to fold (see here for more) an list. :\ folds from right to left and :/ folds from left to right.
scala> list1 res50: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> (1 /: list1)((r,i) => {println(i);i+r}) 0 1 2 3 4 5 6 7 8 9 10 res51: Int = 56 scala> (list1 :\ 1)((i,r) => {println(i);i+r}) 10 9 8 7 6 5 4 3 2 1 0 res52: Int = 56
As you can see the folding direction determines whether the elements are processed from beginning to end or backwards.
And that’s it for this small snippet.
Reference: | Scala snippets 2: List symbol magic from our JCG partner Jos Dirksen at the Smart Java blog. |
there is a error
And then we’ve pretty much covered all except :\ and :/.
should be
And then we’ve pretty much covered all except :\ and /:.