Views can be difficult to understand. It is presented at times in a way that can make it even more difficult to understand. In creating a Scala Koan , I decided to make a koan that makes it easy to grok what a view is all about.
In this example, I create list of Ints 1 through 6 and call it lst. lst has two maps. A map takes a function and invokes that function on each element of a collection.
The first map in my example will print out in stdout what will actually be doubled and then doubles that element. The second map will print that it is adding 1 to each element then adds 1 to each element.
The results:
scala> val lst = 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: Nil
scala> lst.map{x => println("Doubling %s".format(x)); x*2}
.map{x => println("Adding 1 to %s".format(x)); x + 1}
Doubling 1
Doubling 2
Doubling 3
Doubling 4
Doubling 5
Doubling 6
Adding 1 to 2
Adding 1 to 4
Adding 1 to 6
Adding 1 to 8
Adding 1 to 10
Adding 1 to 12
res1: List[Int] = List(3, 5, 7, 9, 11, 13)
What should become blatantly clear is that doing two maps is inefficient. The first map goes through each of items, and the second map will go through each of the items again.
This is where view comes in. When you use a view you can add compound functions to a collection before invoking those functions in one fell swoop using the method force. In other words, you can set up all the functions you want and when you are ready, force the view to calculate your maps (or other functions that you are using on your collection).
In the following example, I do the same exact thing as I did in the previous example but if you notice I have lst.view.map instead of lst.map I create a view of the list so that I can add some functions before actually invoking them.
What I get as a result is a SeqView Object. Once I have the SeqView object, I can then call force and get the same final result as before, except this time you will notice that how
we got there is quite different. This time instead of doubling all the elements, and then adding all the elements, we interweaved our operations for efficiency, and the list was iterated once instead of twice.
scala> lst.view.map{x => println("Doubling %s".format(x)); x*2}
.map{x => println("Adding 1 to %s".format(x)); x + 1}
res2: scala.collection.SeqView[Int,Seq[_]] = SeqViewMM(...)
scala>res2.force
Doubling 1
Adding 1 to 2
Doubling 2
Adding 1 to 4
Doubling 3
Adding 1 to 6
Doubling 4
Adding 1 to 8
Doubling 5
Adding 1 to 10
Doubling 6
Adding 1 to 12
res3: Seq[Int] = List(3, 5, 7, 9, 11, 13)