Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do recursive loops in scala

Tags:

scala

I was wondering if there is a better way to write recursive loops in scala.

def fib(n: Int) = {
  def loop(a: BigInt = 0, b: BigInt = 1, n: Int = n): BigInt = {
    if(n==0) a
    else loop(b, a+b, n-1)
  }
  loop()
}

I could write it like this

def fib(n: Int, a: BigInt = 0, b: BigInt = 1): BigInt = {
  if(n==0) a
  else fib(n-1, b, a+b)
}

but then a and b would be exposed and not encapsulated inside the method anymore.

like image 691
SpiderPig Avatar asked Nov 11 '11 21:11

SpiderPig


People also ask

How does recursion work in Scala?

Recursion refers to a general method that involves defining a solution or object in terms of itself. Recursive functions refer to a kind of function where the definition of a function includes calling the function itself.

Why do we use recursion instead of loops in Scala?

The use of recursion is a more functional approach to writing loops than using a for loop. Scala highly encourages the use of functional loops. Recursive algorithms can sometimes create extremely deep call stacks and exhaust the stack space.

What is tail recursion in Scala?

A recursive function is said to be tail-recursive if the recursive call is the last operation performed by the function. There is no need to keep a record of the previous state. In Scala, you can use @tailrec to check if the recursion is tail-recursive or not. The annotation is available in the scala.

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.


2 Answers

Note that you can often use foldLeft or foldRight in such situations:

def fib(n: Int) = (1 to n).foldLeft((BigInt(0),BigInt(1)))((p,_)=>(p._2,p._1+p._2))._1

[Edit]

Another approach would be an iterator-based solution:

def fib = Iterator.iterate((0,1)){case (x,y) => (y,x+y)}.map(_._1)

This generates an infinite amount of fibonacci numbers, but you can simply take as many as you want from it, e.g. fib.take(10).toList

like image 98
Landei Avatar answered Oct 24 '22 04:10

Landei


Loops have their own scopes. When you replace a loop with a recursive function you are forced to create an explicit scope (the inner method). There is no way around it. This is how it is done. Nothing wrong about it.

like image 1
agilesteel Avatar answered Oct 24 '22 03:10

agilesteel