When using Java/Kotlin for programming is recommended to use Tail recursion or the Iterative version? Is there any difference in performance?

Andrei Paciurca :

I try to learn about good practices in programming and I'm stuck with this question. I know that in Java, recursive functions can be 'a pain in the ass' (sometimes), and I try to implement as much as I can the tail version of that function. Is it worth bothering with this or should I do in the old fashioned way? Is there any difference between this two functions (in Kotlin):

tailrec fun tail_fibonacci(n : BigInteger, fib1 : BigInteger = BigInteger.ZERO , fib2 : BigInteger = BigInteger.ONE) :
BigInteger {
    return when(n){
        BigInteger.ZERO -> fib1
        else -> tail_fibonacci(n.minus(BigInteger.ONE),fib1.plus(fib2),fib1)
    }
}

fun iterative_fibonacci(n: BigInteger) : BigInteger {
    var count : BigInteger = BigInteger.ONE
    var a : BigInteger = BigInteger.ZERO
    var b : BigInteger = BigInteger.ONE
    var c : BigInteger
    while(count < n){
        count += BigInteger.ONE
        c = a + b
        a = b
        b = c
    }
    return b
}
hotkey :

The biggest difference I see is the signatures: while iterative_fibonacci takes one argument and is quite clear, tail_fibonacci takes three, and though the defaults are provided, this might surprise the user. You can, however, make a wrapper function for it, and even make the tailrec function a local one.

There should not be much difference in the resulting bytecode the two functions are compiled to, except for n.minus(BigInteger.ONE) vs count += BigInteger.ONE, and you can check it for yourself with a Kotlin bytecode viewer.

Regarding performance, there should not be any predictable difference between the two implementations (also note that the JVM additionally optimizes the code at runtime with JIT compiler), but of course the tailrec function is much more efficient than an ordinary recursive one would be.

As to the code style (which is highly opinion-based), many tail-recursive solutions look more natural (and closer to math notation), and some do not (e.g. when there are many parameters that end up in a complete mess).

So, I think, tailrec should be used as a performance tool (and especially as a way to avoid stack overflow, which requires all recursive calls to be tail ones) when you find a recursive definition more suitable for expressing what the code does.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

tail recursion performance on template meta-programming

Unexplained behaviour when using tail recursion

When to use long or int in Kotlin? Is there any difference in performance?

Detection of tail recursion in programming langs

The difference between head & tail recursion

R: Is there any performance difference between using = or <-?

Why tail-recursion is a bad use of recursion?

When is tail recursion guaranteed in Rust?

DoublyLinkedList using tail recursion - InsertItem

tail Recursion multiplication using BigInteger

Does it make any difference in Performance when using int or double for JSNI Functions?

is there any big difference of performance?? when using TCP Socket I/O code

Is using -S with JRuby recommended even when using a Ruby version manager?

Is there any performance benefit when we use Limit

Tail recursion fibonacci derived from linear recursive version using Burstall & Darlington's folding/unfolding system

Difference between dynamic programming and recursion

Is it efficient to use Arrays in Recursion, when programming functionally in scala?

Not noticing any performance improvement when using async

Postgresql huge performance difference when using IN vs NOT IN

Is Tail Call optimization all that explains this performance difference

Any performance difference when returning from switch block?

Is there any performance difference between <a> and <button> when used to create link?

Is there any difference within the port Numbers that we use in Socket Programming?

Explanation for tail(?) recursion when calling the method twice

is there any performance difference between using malloc versus realloc?

Is there any performance difference between declaring a variable and using it directly in method in Ruby?

in golang, is there any performance difference between maps initialized using make vs {}

SQL - any performance difference using constant values vs parameters?

Is there any performance difference in using int versus int8_t