3

So I have this recursive function that multiplies two numbers, simple enough.

 def mul(n: Int, m: Int):Int = if(m > 1) n + mul(n, dec(m)) else n 

Now I'm trying to turn it into a tail recursive function, and I tried this:

 def mulWithTail(n: Int, m: Int):Int = { @tailrec def iter(result: Int, x: Int):Int = if(x == 0) result else result + iter(result, dec(x)) iter(n, m) } 

However I get the following error:

error: could not optimize @tailrec annotated method iter: it contains a recursive call not in tail position

else result + iter(result, dec(x))

Question: Can you explain to me why this error is occurring? How should I refactor my code?

1
  • dec() just decrements by one btw Commented Sep 27, 2017 at 6:26

1 Answer 1

8

You can make your function tail recursive simply adding an extra parameter acting like an accumulator. Like this.

def mul(n: Int, m: Int, acc: Int): Int = if (m > 1) mul(n, m - 1, n + acc) else acc 

To make a function tail recursive you must not perform any other operation in the recursion step but calling the function recursively. In your code samples you're performing an addition in the recursion step.

  • n + mul(n, dec(m))

  • result + iter(result, dec(x))

Sign up to request clarification or add additional context in comments.

3 Comments

Can you explain how adding this extra parameter makes it tail recursive?
Sure. Edited to include an explanation.
@PhillipR: Infix operators confuse things in this case. Take a piece of paper and write down the recursive call in pure function call notation, and you will immediately see that the recursive call is not in tail position: plus(result, iter(result, dec(x))). Here, it becomes obvious that the call to iter is wrapped in a call to plus and thus not the last call executed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.