Confusion about whether non-local returns work or not


#1

Hello,

some time ago I read in the documentation about inline functions in the section named “Non-local returns”. I somehow got the impression that those NLR only work in certain cases where the closure can be inlined.

Then I found this code snippet by Andrey Breslav showing some workaround how to do a NLR with wrapping a try-catch block around the lambda. So this then gave to me the impression that you can’t do a NLR in a foreach.

Today I hacked in this code an the NLR there just worked:

fun bar() : Int {
    val list = listOf(1, 2, 3, 4)
    list.forEach {
        if(it >= 2) {
            return it
        }
        println(it)
    }
    println("must not get here")
    return -1
}

fun main(args: Array<String>) {
    val num = bar()
    println(num)
}

The code above compiles and prints correctly to the console:

1
2

So the NLR just worked without any further ado like inline and whatever. And now I’m quite confused when NLR work and when they don’t. The issue in “Non-local returns” only concerns nested lambdas? Other than that NLR are working? If I can rely on them working from within collection iterators (foreach, map, filter, etc.) I’m actually happy enough.


#2

Okay, I’m getting it now: forEach in CollectionsKt is declared with the inline keyword. If I write my own forEach I need to make sure I also declare with inline and things are fine.

I would suggest that the section about NLR shows some sample where you can see a NLR being done from within a forEach, map, filter or whatever. I think this is very important information for people being interested in Kotlin that NLR do work there. At least to me it wasn’t clear at all and misleading and other people might decide not to look any further into Kotlin because they also misunderstand this.

Always thinking they don’t work in Kotlin made me repeatedly think of still using Scala, because if I can’t do a NLR from within a forEach I either change to Scala or just stick to crappy Java streams that also can’t do NLR.


#3


#4

Maybe you remove this Gist https://gist.github.com/abreslav/6916859 or add a comment to it that it no longer applies. Because it can be googled with “Kotlin non-local return” and then gives the impression that it cannot be done in Kotlin.

In the text snippet above in the red box maybe add a remark that forEach was declared with inline for this to work. Then it is much clearer :slight_smile:


#5

I think that the “inline functions often enclose” words right before the example, along with the name of the topic in which this example is found, explain sufficiently clearly that we’re talking about an inline function.

And if people use random 4-year-old gists floating around on the Internet with no context as a source of information, then yes, they can get incorrect impressions about all sorts of things.


#6

Well, then that’s how it may be. For me seeing NLR working from within collection iterators gave me the missing link. Now it’s clear to me that Kotlin with its feature set and clean approach towards language design is the best OO language on the JVM and sooner or later will be the clear number 2 in usage count after Java.