Monday, December 19, 2011

Learning Scala : Reading the exotic and essential List API scaladoc 1

Authored by Win Myo Htet


Everything about data manipulation in Scala is List. Of course, I over exaggerate it. Yet, you will be using List more than any other data structure. I have started out learning Scala and run into List over and over. I even theorize that if you know List API, you know Scala and the majority of its API. After all, the majority of the functions in Scala data structure API overlap. I wish, I had learned the List API early and it would have made my life easier. I would have known about the neat function like mkString when I was reading the Tic Tac Toe code. I wouldn't be doing list.slice(0,list.length-2) or list(list.length-1). It seems silly now. Yes, I have done those things because I have not read or even skimmed the List API doc while I have been using more advanced functions like foldLeft, flatMap and flatten. If you go look at my gist repo and look at the first version of gists, you will see that I am telling the truth.

I don't know about the reader. For me coming from the pretty and greenery Adroid API world, scaladoc seems daunting until I see the C++'s stuff below
template <template <class, class> class C,
          class T,
          class A,
          class T_return,
          class T_arg
              >
C<T_return, typename A::rebind<T_return>::other>
map(C<T, A> &c,T_return(*func)(T_arg) )
{
    C<T_return, typename A::rebind<T_return>::other> res;
    for ( C<T,A>::iterator it=c.begin() ; it != c.end(); it++ ){
        res.push_back(func(*it));
    }
    return res;
}

I feel blessed. Enough with the intro, let's look at the List API. Please open the link in the different browser window while you are reading the blog since I will be referring to it as I talk about the List.

Well, Scaladoc API also is pretty, it's just packed with a lot of information. At the top most section, we have the package name: scala.collection.immutable and then the class name: List. The section is followed by the class signature section stating that List extends LinearSeq and have trait's of Product,  GenericTraversableTemplate and LinearSeqOptimized. [+A] means that List is covariant. Don't worry about [+A], it just likes java Generic.

The description section explains a bit about the class with the missing info from class signature like Attributes : sealed abstract, which means all the sub classes (for List: Nil and ::) of  the sealed class (List) must be in the same source file so that, when the pattern matching is used, the compiler can warn about whether the match is exhaustive or not. We also have the link for easy access to view the source file. You will see Nil on line 368 and :: on line 390 in the same List source file. There are more info about the version numbers. The Linear Supertypes  provide information of the multiple inheritance (without diamond problem).  There is also information on Subclasses.

At first, this section seems like more redundant information about the class with in-page-search box, which is neat. So, let's call this section, "Search section", which we will be using a lot later. This section is really powerful and will make you appreciate this official Scala API. By default, the following is selected Ordering : Alphabetic, Inherited : Show all, Visibility : Public. If you select By inheritance in Ordering, you will see all the List's value members ordered in a way the members are inherited. That way, you can track which member is inherited from which class if you are interested in it. "Hide all" does not really hide all. It leaves List's own concrete value members, which makes sense. From there one can toggle the classes interested in to see the particular class' value member only. Visibility : All will show the protected members also.

Now, we are left with Instance Constructors, Type Members, Abstract Value Members, Concrete Value Members and Deprecated Value Members sections. Instance Constructors is for Constructor method. Type Member can be assumed as inner Class Member, if you are not familiar with the Scala type system yet. Abstract Value Members is the abstract methods without implementation and values without initialization. Concrete Value Members are the ones we will be using. Needless to say, we won't be using any of the Deprecated Value Members.

Let me skip the Constructor stuff and get to Type Members. Here we have the inner class like member WithFilter class. What do we do with this? How are we going to use it? We don't have to do anything with this. Then, why is it there? It is there because List have inherited it from TraversableLike. If you go to Search Section and click on Hide all,  TraversableLike and List (to hide List's stuff) under Inherited, you will still see Type Members class WithFilter along with some Concrete Value Members. If you scroll down, you will see function withFilter in the Concrete Value Members. If you go look at the  TraversableLike source code, you will see this class WithFilter(line 639) and function withFilter(line 634) there. You are like, "Ok, fine, just show me how to use it." Now we know that function withFilter is the one we are interested in for usage.

If we expand and look at the definition of withFilter, we know that it takes a predicate (a function returning a Boolean) as a parameter and return  FilterMonadic stuff. Wow, Scary! Let's read a bit more. There is a note mentioning about the difference between filter and withFilter. If it talks about the difference, it must be similar! It is said that, compare to filter, withFilter does not create a new collection when doing the filtering, thus withFilter is the optimized version of the filter! We want to use the optimized version, withFilter then. There is more info on the FilterMonadic in the return type description. It is said that FilterMonadic is some object which support map, flatMap, foreach and withFilter. Well, let's give it a try then.


scala> val list=List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)

scala> list.withFilter(num=>num%2==0)
res0: scala.collection.generic.FilterMonadic[Int,List[Int]] = scala.collection.TraversableLike$WithFilter@431067af

scala> list.withFilter(num=>num%2==0)foreach(println)
2
4
6
8
10
12
14

scala> list.filter(num=>num%2==0)foreach(println)
2
4
6
8
10
12
14

scala> list.filter(num=>num%2==0)
res3: List[Int] = List(2, 4, 6, 8, 10, 12, 14)

scala> list.filterNot(num=>num%2==0)
res4: List[Int] = List(1, 3, 5, 7, 9, 11, 13, 15)

scala> 


Ah... the FilterMonadic thingy is not scary after all. We just need to use it with map, flatMap, foreach and withFilter only. Now we have knocked withFilter and filter off from the List API's functions list for us to learn. Oh, I have squeezed in the filterNot too if you pay attention.

How do we get to the near bottom of the List API Scaladoc? We come here through Type Memeber. Well, then let's get back to where we are next. Shall we?


Authored by Win Myo Htet

No comments:

Post a Comment