This is intended behavior. The error occurs due to how @tailrec
works: in essence, the compiler tries to transform a recursive call into a local loop. In spite of the fact that your method is recursive, it recurses by calling itself on another instance not even of the same type, but of the supertype - and since other children of TweetSet
may provide a completely different implementation of filterAcc
, the compiler cannot make sure this method can be safely expanded into a loop.
A rule of thumb for tail-recursive functions is to ensure that it always calls exactly itself as the last statement - in your case, instead of calling
(this remove elem).filterAcc(...)
you have to try and transform acc
in the way that emulates this remove elem
and call
filterAcc(p, <transformed acc>)
In functional programming involving recursion it is a good idea to define the entire method in the superclass (in your case TweetSet
) and rely on pattern matching by ADT members instead of polymorphism - that way there will be no issues with optimizing recursion.
Upd: There's a nice blog post explaining tail recursion, as specified in an answer to this question