Nested inline functions is not supported yet?

Does nested inline functions will be supported in the future?

inline fun f1(block1: () -> Unit) {
    inline fun f2(block2: () -> Unit) { // construction is not yet supported in inline functions
        block2()
    }

    block1()
}
2 Likes

The answer is maybe. It’s not very simple, so we are looking for use cases

The obvious use-case is avoiding synthetic classes + closure allocations.

I’m working on a deep-learning project, where we have a lot of logic and juggling with local vals.
Packing the individual logic branches into local functions makes the solution more readable, but worse in regards to memory.

Based on the decompiled java code, it seems that merely declaring a local function will eagerly create a new closure-object. Even though the local function may not have been called at all.

Kotlin:

fun localFuns() = run {
    val condition2 = "blue"
    val condition3 = 10

    fun getResult1() = if (condition3 == 5 && condition2 == "blue") "OK1" else null
    fun getResult2() = if (condition3 == 10 && condition2 == "red") "OK2" else null

    getResult1() ?: getResult2() ?: "NOT OK"
}

Java version:

   public static final String localFuns() {
      int var0 = false;
      String condition2 = "blue";
      int condition3 = 10;
      EnrichmentControllerKt$localFuns$1$1 $fun$getResult1$1 = new EnrichmentControllerKt$localFuns$1$1(condition3, condition2);
      EnrichmentControllerKt$localFuns$1$2 $fun$getResult2$2 = new EnrichmentControllerKt$localFuns$1$2(condition3, condition2);
      String var10000 = $fun$getResult1$1.invoke();
      if (var10000 == null) {
         var10000 = $fun$getResult2$2.invoke();
      }

      if (var10000 == null) {
         var10000 = "NOT OK";
      }

      return var10000;
   }

I would not ask this , if the second closure-object was created lazyly, only when the function could not return based on the first local function’s result.

Sad to see such low demand for this :frowning: .

1 Like

Kotlin 1.8

Unfortunately I cannot declare a local inline function even inside a regular one. I wanted to restrict access to it only within the host function, because it’s not designed to be used somewhere else. However, I had to pull it out and make it visible to all other methods inside the class… My use case was to print additional logging on failed type casts within a method.

fun target(a: A) {
    inline fun <reified T: A> cast(obj: A): T? { // fails to compile
        return (obj as? T).also {
            if (it == null) println("not casted to ${T::class.java.simpleName}")
        }
    }
    // ... use cast<...>(a) here several times ...
}

When I declare this auxiliary function inside the target one, the IDE underlines the inline keyword with red. But without inline I cannot use reified, thus safe type casts and the class name become unavailable.