Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala uses mutable variables to implement its apis

I am in the process of learning Scala through Coursera course (progfun).

We are being learned to think functionally and use tail recursions when possible to implement functions/methods.

And as an example for foreach on a list function, we have taught to implement it like:

def foreach[T](list: List[T], f: [T] => Unit) {
    if (!list.isEmpty) foreach(list.tail) else f(list.head)
}

Then I was surprised when I found the following implementation in some Scala apis:

override /*IterableLike*/
  def foreach[B](f: A => B) {
    var these = this
    while (!these.isEmpty) {
      f(these.head)
      these = these.tail
    }
}

So how come we are being learned to use recursion and avoid using mutable variables and the api is being implemented by opposite techniques?

Have a look at scala.collection.LinearSeqOptimized where scala.collection.immutable.List extend. (similar implementation found in the List class itself)

like image 273
Muhammad Hewedy Avatar asked Jul 12 '15 14:07

Muhammad Hewedy


2 Answers

Don't forget that Scala is intended to be a multiparadigm language. For educational purposes, it's good to know how to read and write tail-call recursive functions. But when using the language day-to-day, it's important to remember that it's not pure FP.

It's possible that part of the library predated TCO and the @tailrec annotation. You'd have to look at commit history to find out.

That implementation of foreach might use a mutable var, but from the outside, it appears to be pure. Ultimately, this is exactly what TCO would do behind the scenes.

like image 181
Daniel Yankowsky Avatar answered Oct 13 '22 01:10

Daniel Yankowsky


There are two parts to your question:

So how come we are being learned to use recursion and avoid using mutable variables

Because the teachers assume that you either already know about imperative programming with mutable state and loops or will be exposed to it sometime during your career anyway, so they would rather focus on teaching you the things you are less likely to pick up on your own.

Also, imperative programming with mutable state is much harder to reason about, much harder to understand and thus much harder to teach.

and the api is being implemented by opposite techniques?

Because the Scala standard library is intended to be a high-performance industrial-strength library, not a teaching example. Maybe the person who wrote that code profiled it and measured it to be 0.001% percent faster than the tail-recursive version. Maybe, when that code was written, the compiler couldn't yet reliably optimize the tail-recursive version.

Don't forget that Iterable and friends are the cornerstone of Scala's collections library, those methods you are looking at are probably among the most often executed methods in the entire Scala universe. Even the tiniest performance optimization pays out in a method that is executed billions of times.

like image 37
Jörg W Mittag Avatar answered Oct 13 '22 00:10

Jörg W Mittag