Kotlin is elegant because it capture’s programmer intent succinctly, not because it guesses programmer intent.
One of the problems with Java and C# is a lack of transparency – it’s often hard to tell if a section of code will actually be performant or not because of the JITing behavior of the JVM. Escape analysis and method inlining (among numerous other JIT optimizations), while good for performance, make it hard to reason about what the program is actually going to do at runtime.
Admittedly, since Kotlin runs on the JVM, we still have that problem, but we’re given additional tools to add some determinism.
inline, for instance, forces that method to be inlined at compile time, instead of hoping it’ll be inlined at runtime. That’s quite nice. It’s more verbose, but enables the developer to specify exactly what they want. And it’s just one keyword.
tailrec is another.
The problem with tail recursive calls is that it’s way more than a matter of performance. (I’m not really familiar with the algorithm you chose for your example, so I’ll use fibonacci instead). If you implement a naive fibonacci-calculating function recursively, you’ll probably want to use
tailrec. Then you can say
fibonacci(100), and it’ll still work. The latter might be slow, but it’ll work. Now, if tail recursion was implicit…well, it might still work. But what if you make an “optimization” to your algorithm? Try to make it a bit faster, but still hoping that Kotlin/JVM will use tail recursion. If you’re wrong, the program will crash with StackOverflowError randomly for certain inputs, inputs you might not even be testing for! It introduces a “denial of service” vector to your function. On the other hand, if you knew you had to have tail recursion for this function (because you wrote it a certain way and know the stack might otherwise get too deep), then the
tailrec keyword will ensure you won’t hit that dreaded StackOverflowError ever again. Anything that acts as guard rails to keep our software running smoothly I’m quite in favor of, even if it means an extra keyword.