Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Scala snippets 2: List Symbol Magic

DZone's Guide to

Scala snippets 2: List Symbol Magic

· Java Zone
Free Resource

The single app analytics solutions to take your web and mobile apps to the next level.  Try today!  Brought to you in partnership with CA Technologies

The following other snippets are also available:

  1. Scala snippets 1: Folding

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 easier.

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
     
       = 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 ([a href="http://www.smartjava.org/content/scala-snippets-1-folding" style="color: rgb(34, 98, 164); outline-style: none; text-decoration: none;"]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.

CA App Experience Analytics, a whole new level of visibility. Learn more. Brought to you in partnership with CA Technologies.

Topics:

Published at DZone with permission of Jos Dirksen, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}