Manu Chadha Manu Chadha - 17 days ago 5
Scala Question

andThen in List scala

Has anyone got an example of how to use andThen with Lists? I notice that andThen is defined for List but the documentations hasn't got an example to show how to use it.

My understanding is that f andThen g means that execute function f and then execute function g. The input of function g is output of function f. Is this correct?

Question 1 - I have written the following code but I do not see why I should use andThen because I can achieve the same result with map.

scala> val l = List(1,2,3,4,5)
l: List[Int] = List(1, 2, 3, 4, 5)

//simple function that increments value of element of list
scala> def f(l:List[Int]):List[Int] = {l.map(x=>x-1)}
f: (l: List[Int])List[Int]

//function which decrements value of elements of list
scala> def g(l:List[Int]):List[Int] = {l.map(x=>x+1)}
g: (l: List[Int])List[Int]

scala> val p = f _ andThen g _
p: List[Int] => List[Int] = <function1>

//printing original list
scala> l
res75: List[Int] = List(1, 2, 3, 4, 5)

//p works as expected.
scala> p(l)
res74: List[Int] = List(1, 2, 3, 4, 5)

//but I can achieve the same with two maps. What is the point of andThen?
scala> l.map(x=>x+1).map(x=>x-1)
res76: List[Int] = List(1, 2, 3, 4, 5)


Could someone share practical examples where andThen is more useful than methods like filter, map etc. One use I could see above is that with andThen, I could create a new function,p, which is a combination of other functions. But this use brings out usefulness of andThen, not List and andThen

Answer

andThen is inherited from PartialFunction a few parents up the inheritance tree for List. You use List as a PartialFunction when you access its elements by index. That is, you can think of a List as a function from an index (from zero) to the element that occupies that index within the list itself.

If we have a list:

val list = List(1, 2, 3, 4)

We can call list like a function (because it is one):

scala> list(0)
res5: Int = 1

andThen allows us to compose one PartialFunction with another. For example, perhaps I want to create a List where I can access its elements by index, and then multiply the element by 2.

val list2 = list.andThen(_ * 2)

scala> list2(0)
res7: Int = 2

scala> list2(1)
res8: Int = 4

This is essentially the same as using map on the list, except the computation is lazy. Of course, you could accomplish the same thing with a view, but there might be some generic case where you'd want to treat the List as just a PartialFunction, instead (I can't think of any off the top of my head).


In your code, you aren't actually using andThen on the List itself. Rather, you're using it for functions that you're passing to map, etc. There is no difference in the results between mapping a List twice over f and g and mapping once over f andThen g. However, using the composition is preferred when mapping multiple times becomes expensive. In the case of Lists, traversing multiple times can become a tad computationally expensive when the list is large.

Comments