Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any advantage to avoiding while loops in Scala?

Tags:

scala

Reading Scala docs written by the experts one can get the impression that tail recursion is better than a while loop, even when the latter is more concise and clearer. This is one example

object Helpers {
    implicit class IntWithTimes(val pip:Int) {
            // Recursive
        def times(f: => Unit):Unit = {
            @tailrec
            def loop(counter:Int):Unit = {
                if (counter >0) { f; loop(counter-1) }
            }
            loop(pip)
        }

            // Explicit loop
        def :@(f: => Unit) = {
            var lc = pip
            while (lc > 0) { f; lc -= 1 }
        }   
    }
}   

(To be clear, the expert was not addressing looping at all, but in the example they chose to write a loop in this fashion as if by instinct, which is what the raised the question for me: should I develop a similar instinct..)

The only aspect of the while loop that could be better is the iteration variable should be local to the body of the loop, and the mutation of the variable should be in a fixed place, but Scala chooses not to provide that syntax.

Clarity is subjective, but the question is does the (tail) recursive style offer improved performance?

like image 958
Mike Hanafey Avatar asked Sep 07 '13 15:09

Mike Hanafey


People also ask

Why loops are discouraged in Scala?

Conclusion. As we know loops cause mutation and scala adheres to the principle of immutability, Hence recursive functions are preferred over loops in scala. So when you need loops, Use Recursion and when you need Recursion.

Should you use loops in Scala?

If you heard about loops in Scala, try to forget them. Try to do without them. Instead of asking “how can I loop through this”, ask “how can I transform this”. Take this one principle to heart and you'll be ahead of many Scala programmers already.

Should you ever use a while loop?

In general, you should use a for loop when you know how many times the loop should run. If you want the loop to break based on a condition other than the number of times it runs, you should use a while loop.

Is there a benefit to using a while loop over a for loop?

The main advantage of a for loop over a while loop is readability. A For loop is a lot cleaner and a lot nicer to look at. It's also much easier to get stuck in an infinite loop with a while loop.


1 Answers

I'm pretty sure that, due to the limitations of the JVM, not every potentially tail-recursive function will be optimised away by the Scala compiler as so, so the short (and sometimes wrong) answer to your question on performance is no.

The long answer to your more general question (having an advantage) is a little more contrived. Note that, by using while, you are in fact:

  1. creating a new variable that holds a counter.
  2. mutating that variable.

Off-by-one errors and the perils of mutability will ensure that, on the long run, you'll introduce bugs with a while pattern. In fact, your times function could easily be implemented as:

def times(f: => Unit) = (1 to pip) foreach f

Which not only is simpler and smaller, but also avoids any creation of transient variables and mutability. In fact, if the type of the function you are calling would be something to which the results matter, then the while construction would start to be even more difficult to read. Please attempt to implement the following using nothing but whiles:

def replicate(l: List[Int])(times: Int) = l.flatMap(x => List.fill(times)(x))

Then proceed to define a tail-recursive function that does the same.


UPDATE:

I hear you saying: "hey! that's cheating! foreach is neither a while nor a tail-rec call". Oh really? Take a look into Scala's definition of foreach for Lists:

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

If you want to learn more about recursion in Scala, take a look at this blog post. Once you are into functional programming, go crazy and read Rúnar's blog post. Even more info here and here.

like image 98
Hugo Sereno Ferreira Avatar answered Nov 16 '22 00:11

Hugo Sereno Ferreira