Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin - How to recursively call a lambda function

I'm trying to re implement the linrec function from here in Kotlin. Here is what it currently looks like in Kotlin:

fun <A, B> linrec(indivisible: (List<A>) -> Boolean,
                  value: (List<A>) -> B,
                  divide: (List<A>) -> List<List<A>>,
                  combine: (A, B) -> B
                  ) : (List<A>) -> B {
  val myfunc: (List<A>) -> B = { input ->
    if (indivisible(input)) {
      value(input)           
    } else {
      val split = divide(input)
      val left = split[0][0]
      val right = myfunc(split[1])  // Error
      combine(left, right)   
    }
  }
  return myfunc
}

IntelliJ gives me the following errors, when I try to run the code:

Error:(40, 19) Kotlin: Unresolved reference: myfunc

My question is: How do I make a lambda function call itself?

like image 798
M Krane Avatar asked Jan 03 '17 19:01

M Krane


People also ask

Can lambda functions be called recursively?

This is an example of a function that will recursively call itself. Warning It's possible to run into infinite loops with recursive calls. Test your functions locally before deploying to production.

Does Kotlin have Tail Recursion?

Rules for Tail Recursion in Kotlin To implement a function in Kotlin using tail recursion, there is one rule to follow: the recursive call must be the very last call of the method. This works perfectly well.


1 Answers

You don't call a lambda ("anonymous function") from inside itself. That's what functions are for:

fun <A, B> linrec(indivisible: (List<A>) -> Boolean,
                  value: (List<A>) -> B,
                  divide: (List<A>) -> List<List<A>>,
                  combine: (A, A) -> B
                  ) : (List<A>) -> B {

  fun myfunc(input: List<A>): B {     // rearranged things here
    return if (indivisible(input)) {  // added `return`
      value(input)           
    } else {
      val split = divide(input)
      val left = split[0][0]
      val right = myfunc(split[1])
      combine(left, right)            // *   
    }
  }
  return ::myfunc
}

Now this is exactly the code you've wrote, but it does not compile. On the line I marked with * kotlinc says Type mismatch: inferred type is B but A was expected.

P.S. I have no idea what that code is doing, so I only fixed the compilation error you've asked about.

like image 152
voddan Avatar answered Oct 10 '22 03:10

voddan