In your case the function is not tail recursive, but the reason is a bit different - there is no waiting, the program is executed sequentially and left.sumAcc
is evaluated before right.sumAcc
, however this is still a problem, as the left.sumAcc
call is recusive, but not in the tail position. Even if you would remove this, there are other problems with your solution.
To check if tail recursion can be applied for the function, you can use the @tailrec annotation. In your case, the compiler error message will be:
Error:(11, 7) could not optimize @tailrec annotated method sumAcc: it is neither private nor final so can be overridden
def sumAcc(acc: Int) = right.sumAcc(left.sumAcc(elem + acc))
Why this happens is explained in Why won't the Scala compiler apply tail call optimization unless a method is final? question:
Unless a method is marked final, it might not be calling itself when it makes a recursive call.
This is also what the compiler will tell you if you try to add final to the NonEmpty
sumAcc
. The error message will change to:
Error:(11, 38) could not optimize @tailrec annotated method sumAcc: it contains a recursive call targeting supertype NonEmpty.this.right.type
final def sumAcc(acc: Int) = right.sumAcc(left.sumAcc(elem + acc))
The solution linked in the comment by Millie Smith overcomes this by not using overriding to implement the function, pattern matching (i.e. type check in the function) is used instead, therefore one function is handling the traversal for both Leaf
and Node
types, and the function is structured so that only one call to sumAcc
is done in each case.