Scala Programming – Decreasing Vars

functional programmingimmutabilityscala

I have been studying scala for the past week or so and the ideologies associated with it and functional programming in general. As expected, the leap from imperative to functional programming is not as easy as I had hoped. For example, I converted a programming exercise that I did in Java into Scala. What I found was that it was near impossible for me to switch from mutable variables into the Scala style of immutable vals.

For the TL;DR people, my main question is, how does one decrease the var usage in a functional program? For the sake of a use case, I'll provide some sample code:

import scala.io._
object Bowling {
  def main(args: Array[String]): Unit = {
    val input = Source.fromFile("bowling.in").getLines
    for(testCase <- input) {
      val numberOfRows = augmentString(testCase).toInt
      var index = 0
      var a = 1
      var sum = 0
      while(index < numberOfRows) {
        sum += a
        a += 4
        index += 1
      }
      println(sum)
    }
  }
}

EDIT:
I'm accepting Karl's answer because of its conciseness though I do really appreciate Ptharien's code example and Doval's explanation of functional concepts as a whole.

Best Answer

The general approach is instead of mutating a variable in a loop, put the values into collections and run a series of operations on those collections. Note that most of the time, functional algorithms don't need index variables. Look for mathematical relationships that allow you to factor those out. For example:

val sums = for(testCase <- input) yield {
  val numberOfRows = testCase.toInt
  val a = 1 until numberOfRows * 4 by 4
  a.sum
}
sums foreach println

Just because it's a series of operations on a collection doesn't mean you have to cram all the operations together one after another. Don't forget to break up lines, name intermediate results, and use named functions instead of lambdas where appropriate. The compiler essentially optimizes out numberOfRows and a, but putting them in there adds a lot of readability for humans.

Don't avoid for comprehensions just because of their superficial resemblance to mutated for loops. They are often the key to better readability.

Note I moved the println to outside the for comprehension. Isolating side effects like that can often make it easier to see a pure functional solution for the rest of the problem.

Also, as an aside, you don't need the augmentString. It is implicitly added for you.

Related Topic