Tailrec in get() functions?


I’m wondering if there is any particular reason, why the tailrec keywoard cannot be applied to get() functions.

I’m trying to add an extension property Throwable.rootCause which is an excellent candidate for tail recursion, but I can only use tail-recursion when I define it as a function:

tailrec fun Throwable.getRootCause() : Throwable {
    val c = this.cause
    return if (c == null) this else c.getRootCause()

It doesn’t work to make a tailrec getter function:

val Throwable.rootCause: Throwable
tailrec get() {
    val c = this.cause
    return if (c == null) this else c.rootCause


The error is: "modifier ‘tailrec’ is not applicable to ‘getter’.

The workaround is relatively easy but it made me wonder if there was any particular reason for this restriction, or any plans to lift it (couldn’t find any with a quick search but I didn’t make an exhaustive search).

1 Like

I’m not sure of a technical reason, but I think one thing to consider when deciding between a val and a fun is that developers usually consider properties to be quick and not involve much computation. Even though your example may be quick, the normal use case for tail recursion is not. I’d say that you should probably just not use the tailrec keyword here and keep your extension value. If you actually need the benefits of tail recursion optimization, then I would say using a val is not the right choice.

1 Like

You’re right of course, if one would need the benefits of tail-recursion for digging down the stack of nested exceptions, something’s gone horribly wrong in the design of your software… :smiley: