Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic Scala solution to imperative code

What are some ideas for expressing this function in 'idiomatic' Scala. Or more precisely, is there a way to remove the local vars without sacrificing readability?

def solve(threshold: Int)(f: Int => Int): Int = {
  var sum = 0
  var curr = 0
  while(sum < threshold) {
   sum += f(curr)
   curr += 1
  }
  curr
}

The only thing I could come up with was this, but it's longer and less readable in my opinion.

def solve2(threshold: Int)(f: Int => Int): Int = {
  val resultIterator = Iterator.iterate (0, 0) { case (curr, sum) =>
    (curr + 1, sum + f(curr))
  }
  (resultIterator find (_._2 >= threshold)).get._1
}
like image 215
Garrett Rowe Avatar asked Dec 30 '11 19:12

Garrett Rowe


2 Answers

def solve(threshold: Int)(f: Int => Int): Int = {
  Iterator.from(0).map(f).scanLeft(0)(_ + _).indexWhere(threshold <=)
}

In my opinion, the loop version is much clearer.

like image 139
missingfaktor Avatar answered Sep 29 '22 15:09

missingfaktor


The most direct approach is to turn the while loop into a nested tail-recursive function.

def solve(threshold: Int)(f: Int => Int): Int = {
    def solveLoop(sum: Int, curr: Int): Int = if (sum < threshold) {
        solveLoop(sum + f(curr), curr + 1)
    } else {
        curr
    }
    solveLoop(0,0)
}

This is the standard "functional" way of looping.

like image 37
Dan Simon Avatar answered Sep 29 '22 15:09

Dan Simon