Friday, October 15, 2010

Starting Scala



I'm starting to learn Scala. I try to learn a new programming language every year (a tip from the Pragmatic programmer) because it's a good way to keep your head young. Last year I learned JavaFx Script, too bad that Oracle announced that they are not going forward with this. I really liked the whole notion of binding.

Anyway Scala is a functional language, so that will be a challenge, because I've never written any code in a functional language before. I'm still learning so I thought let's take something form my day to day job.

This was the problem, we have a web service that we can only call with 100 ids at a time. So we need to split our list with ids in batches of a 100. Fist I thought there must be some library that can do this. We did some google-ing, but we could not find it, so this is what we came up with:


static <E> List<List<E>> subDivide(List<E> list, int size) {
List<List<E>> resultList = new ArrayList<List<E>>();

int subdivideCount = list.size() / size;
if (list.size() % size != 0) {
subdivideCount++;
}

for (int i = 0; i < subdivideCount; i++) {
int maxLength = Math.min(i * size + size, list.size());
resultList.add(list.subList(i * size, maxLength));
}

return resultList;
}


Very standard way to solve something like this in Java. So I thought let's solve this in Scala. List are very cool in Scala and you can do pattern matching on them. Let's try that:


def subDivide(list: List[Int], batchSize:Int):List[List[Int]] = list match {
case Nil => Nil
case l if l.length > batchSize => List(list.splitAt(batchSize)._1) ::: subDivide(list.splitAt(batchSize)._2, batchSize)
case l => List(list)
}


As you can see this code is much nicer. It checks the size of the list taking the batchSize off and then sub dividing the rest and adding this to the result. If the size is smaller than the batchSize we can return it without splitting. If anyone knows a better way of doing this in Scala, please leave me a comment.

This is a much nicer solution, because there is way less int calculation involved. And the recursion also makes it a lot nicer, because there is no need of a for loop. So maybe this is what people are talking about, Scala does make you solve things differently.

But of course we could do this in Java as well. In Java we don't have a nice pattern matching, so we'll have to do with if-s.


static <E> void subDivide(List<E> list, int size, List<List<E>> result) {
if (list.isEmpty()) {
return;
}
if (list.size() > size) {
result.add(list.subList(0, size));
subDivide(list.subList(size, list.size()), size, result);
} else {
result.add(list);
}
}


As you can see a lot better. So at least Scala improved my Java code a bit today.

No comments: