The documentation for Kotlin is now located on the new site. This page is kept for historical reasons
Skip to end of metadata
Go to start of metadata
The documentation for Kotlin is now located on the new site. This page is kept for historical reasons

There are three so-called structural jump operators that are sort of like goto but much nicer: return, break and continue. By default, their behavior is as follows:

  • return returns from the nearest enclosing function, and not a function literal
  • break terminates the nearest enclosing loop
  • continue either proceeds to the next step of the nearest enclosing loop or to the next branch in the nearest enclosing when expression

Break and continue at labels

Any expression in Kotlin may be marked with a label. Labels have the from of the @ sign followed by an optional identifier, for examples @, @abc, @fooBar are valid labels (see the grammar). To label an expression, we just put a label in front of it:

@loop for (i in 1..100) { 
  // ... 
}

Now, we can qualify a break or continue with a label:

@loop for (i in 1..100) { 
  for (j in 1..100) { 
    if (...) 
      break@loop 
  } 
}

A break qualified with a label jumps to the execution point right after the loop marked with that label. A continue proceeds to the next iteration of that loop.

Return at labels

With function literals, local functions and object expression, functions can be nested in Kotlin. Qualified return's allow us to return from an outer function. The most important use case is returning from a function literal. Recall that when we write this:

fun foo() { 
  ints.forEach { 
    if (it == 0) return 
    print(it) 
  } 
}

The return expression returns from the nearest enclosing function, i.e. foo. If we need to return from a function literal, we have to label it and qualify the return:

fun foo() { 
  ints.forEach @lit { 
    if (it == 0) return@lit 
    print(it) 
  } 
}

Now, it returns only from the function literal. Often times it is more convenient to use the shortest implicit label @ for function literals:

fun foo() { 
  ints.forEach { 
    if (it == 0) return@ // Works if there's one and only one function literal in lexical scope up to named entity (function or class) 
    print(it) 
  } 
}

Note that such non-local returns are supported only for function literals passed to inline-functions.

When returning a value, the parser gives preference to the qualified return, i.e.

return@a 1

means "return 1 at label @a" and not "return a labeled expression (@a 1)".

Named functions automatically define labels:

fun outer() { 
  fun inner() { 
    return@outer // the label @outer was defined automatically 
  } 
}
Non-local returns are not implemented yet
See the corresponding issue.

Break and continue in custom control structures

Inline functions make writing performant "custom control structures" easy, for example, the forEach() function that executes a function literal for every element in a collection:

inline fun <T> Collection<T>.forEach(body : (item : T) -> Unit) { 
  for (item in this) { 
    body(item) 
  } 
}

Note that this function is not exactly a redundant example easily substitutable by a normal for loop. Consider the following code:

ints filter {it > 0} sortby {-it} forEach {print(it)}

Now, what happens when we write break (or continue) inside the body of forEach? We simply get a compile-time error, because, lexically, there's no loop to break:

ints forEach { 
  if (it < 0) 
break
 // Error: 'break' does not belong to a loop 
  print(it) 
}

But, actually, there is a loop, hidden inside forEach, and it is inlined there, so we should be able to tell the compiler to understand that. An we can, by annotating the loop inside forEach with the loop annotation. The function parameter should also be annotated with loopbody annotation:

inline
 fun <T> Collection<T>.forEach(
loopbody
 body : (item : T) -> Unit) { 
  [
loop
] for (item in this) { 
    body(item) 
  } 
}

Now, the compiler allows break and continue in the function literal argument passed to forEach, and these operators apply to the loop marked with @@.

Break and continue for custom control structures are not implemented yet
See the corresponding issue.

Qualified this expressions

See This expressions.

What's next

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jul 21, 2011

    Non-local break & return flesh out the idea of language macros, together with the inline annotation and your clever handling trailing of function literals in method signatures.  I watch developments here eagerly.

    I am concerned with the intrinsic complexity of non-locality for program comprehension.   Your example with loopbody (I like the earlier "breakable" better, by the way) helps in that there is a hint to the reader something mysterious may be happening.  Is this a strict requirement?

    1. Jul 21, 2011

      > Is it strict requirement?
      Yes, and it also helps foreach-like function developers to make sure @@ is in place and body() is actually called, and it is called just once etc.

  2. Aug 24, 2011

    Rereading this section, I find the syntax for "return" v. "return@" too subtle and prone to typo bugs.  Both are valid syntax, so the compiler won't help.  Perhaps, as the feature would be a less commonly used one, it would be better to avoid any kind of default behavior and require everything to be explicit rather than having an "unnamed label" on the function literal.  I might even to so far as to require some kind of mandatory syntax to distinguish the two "return" cases in the function literal example, although that would lose the elegance of the simple "return" keyword.

    Further, is "return@1 a" and "return @a 1" the same?  It would be terrible for the second to be a labeled expression!  (This question reminds me of the whitespace quirk in C++ with parsing templates v. less-than operator.)

    I am still suspicious of "loopbody" and "@@".  They look inelegant compared to how nicely you have handled other language features. 

    1. Aug 24, 2011

      > Further, is "return@1 a" and "return @a 1" the same?
      No

      > I am still suspicious of "loopbody" and "@@". They look inelegant compared to how nicely you have handled other language features.
      Agreed. We are looking for a better solution.

  3. Sep 02, 2011

    Typo in the section "Break and continue is custom control structures": probably you mean "every" not "exery".

    1. Sep 02, 2011

      Fixed, thanks.

  4. Sep 29, 2011

    Anonymous

    I found at last the thing I don't like in Kotlin !  Why return is not good enough for function literal ? Groovy use the approach and we are happy. In any case a symbol @ looks awfully.

    1. Sep 29, 2011

      I totally agree about '@'. We should change this syntax to something better.
      The idea behind non-local returns is the following:

      Suppose, you have your custom loop, e.g. foreach. You'd really like to use it as a regular loop, and this implies the ability to return from the outer function if you are done. For example:

      fun findFirstEven(c : Collection<Int>) : Int? { 
        c.foreach { 
          if (it % 2 = 0) return it 
        } 
        return null 
      }
      1. Sep 29, 2011

        Anonymous

        Ok. Every time I write a function literal I must keep in mind " It is NOT a FUNCTION it is a FUNCTION LITERAL.

        val myMin = {(x : Int, y : Int) : Boolean => if ( x <= y ) return x else return y }

        Ok. Every time I write a function literal I must keep in mind " It is NOT a FUNCTION it is a FUNCTION LITERAL.

        1. Sep 29, 2011

          I see your point. The question is whether the other option is better:

          whenever you say return, you must be aware of what do those curly braces you are currently in mean: is it a block (like in if) or a function literal...

          To me it is much more difficult.

          1. Sep 29, 2011

            Anonymous

            May be better to save the same meaning of the return keyword for function and function literal  but

            use return@funname expr to break an internal loop (as for nested function). And if Collection has foreach method then let it have find method.

            1. Sep 29, 2011

              So, you propose to prohibit this:

              fun foo() { 
                for (x in xs) { 
                  if (...) return // Compilation error? 
                } 
              }
              1. Sep 29, 2011

                Anonymous

                No. Under internal loop I've meant a loop inside your foreach implementation. 

                If we can write:

                As I understand this means than when it == 0  then the next  statement to be executed is:

                print("it == 0")

                But if I write:

                then if there is an item with a zero value than  print("it == 0")doesn'texecute.So, why cannnot we write:

                Here return@foo means return from the outer function and return means return from the function litral.

                1. Sep 29, 2011

                  Your case about @lit simulates what break usually does. This'd betted be done by break itself. See [Break and continue in custom control structures].

                  In the current design of Kotlin if you say return@lit it returns from what's marked with @lit, i.e. the function literal. And this looks pretty consistent to me.

          2. Dec 31, 2011

            Given that several popular languages have only the notion of first-class and anonymous functions and people seem to cope just fine, nonlocality by default seems too counter-intuitive and too prone to confusion for little to no gain. In times of increasing attention to more functional techniques (no pun intended :), fiddling with control structures sounds like an odd throwback to make in (almost) 2012.

            whenever you say return, you must be aware of what do those curly braces you are currently in mean: is it a block (like in if) or a function literal...

            This discussion reminds me of a post in Neal Gafter's blog about closures in Java (in 2006...), where he discussed using closures synchronously (like loop blocks) or asynchronously (like callbacks), which is the same problem Kotlin currently solves with function literals and nonlocal jumps. I'm not so hot on his proposal either (and the comment section provides some very relevant points), because the problem is that there are two separate concepts here: closures (as in Neal's async closures and what most other popular languages use) and blocks (Neal's sync closures, Kotlin's function literals). Both are being conflated together because they're almost the same thing, but those little differences cause the hackery needed to close the gap. The way I see it, the difficulty mentioned in the quote above is because closures and blocks should be separate concepts but they aren't.

            Between both, proper closures are the most important thing to have; nonlocality is rarely a good idea. But if you guys really want blocks, they should be distinguished from closures, both syntactically and in the type system. Maybe some way to use one as another when valid (not so sure about this idea). Although Lisp programmers (and the link above has a comment towards the end of the page that caught my attention) may scoff and say that you really want are macros :)

            1. Dec 31, 2011

              I would like to point one thing out:

              nonlocality by default seems too counter-intuitive

              This heavily depends on what background you come from. And we expect the majority of the audience to come from Java background.

              1. Dec 31, 2011

                I wandered around a bit, but my background and bread-earner is still Java, and when I read the name function literals I understood closures. Given inner classes, that's a very small leap to a purely Java programmer to take, and languages like Groovy, C# and Ruby show that the concept of closures is no big deal for the average coder, and popular enough for function literals to be a controversial feature. 

                The main point I wished to make is that intuitively, one reads function literals and thinks closures, when what Kotlin has defined here are blocks. If Kotlin had called it blocks I'd be curious to why there aren't any closures, but I wouldn't be confused :)

                1. Dec 31, 2011

                  The only thing that distinguishes blocks from "closures" in your terms seems to be the meaning of return. What do you think about prohibiting return in "closures", i.e. having them return the last expresson in the body, as most functional languages do? Does this seem to eliminate the problem?

                  1. Jan 01, 2012

                    I'm thinking of this definition for closures; if what I've written here doesn't match, trust the link, or, even better, trust the (long) literature on the subject :) 

                    What do you think about prohibiting return in "closures", i.e. having them return the last expresson in the body, as most functional languages do?

                    No good... It would be like having no continue statement for loops (like Lua, up until 5.2), or, well, function literals; you can still make it work how you want it to, but it's more awkward than it needs to be. And, as I understand it, returning the last expression in the body works well when you have a small body. For bigger stuff, having return so you can stop processing as early as possible is very useful. Forbidding return for closures is arbitrary; it doesn't look like an elegant feature, or even a necessary tradeoff, it looks like a hack.

                    Neal Gafter's blog post delves much better than I could into the diference between what I'm calling blocks (his synchronous closures) and closures (his asynchronous closures), although his solution is debatable too. 

                    If I had to choose between one or another, I'd go with closures: they're well understood, well known (Java's inner classes are already halfway there, and Javascript, Ruby, C# and Groovy, among others, popularized the notion further), and there's a wealth of techniques and patterns available in academia and mainstream to use and compose them well. But, yes, they don't fit well in Neal's sync cases. Blocks solve elegantly Neal's sync cases, but don't fit in his async cases. And aren't as well known. 

                    The best solution I see is to offer both, and make them have different types, syntax and semantics. Closures work like full blown first-class functions, but don't accept break, continue and nonlocal returns, and blocks work mostly as advertised above, and are automatically inlinable, which makes intuitive sense to me given the nonlocality.

                    Several issues remain:

                    • with different types, functions can specify which one they expect, although maybe some conversion operation from one to another will be needed in the language;
                    • what happens with the labels?
                    • what syntax to use?

                    But this solution seems better to me.

                    Update: fixed the link.

                    1. Jan 01, 2012

                      Got your point, thanks

      2. Jan 18, 2012

        I totally agree about '@'. We should change this syntax to something better.

        May I suggest a syntax like this: name.return, name.break etc.

  5. Feb 17, 2012

    Please explain some points from this example:

    1. Why in "body" function type definition  parameter name is provided(item)?

    2. Maybe loop content need need to be

    instead of
    ?

    1. Feb 17, 2012

      > 1. Why in "body" function type definition parameter name is provided(item)?
      We allow parameter names in function types for two reasons:

      • as a matter of (optional) documentation
      • to allow named arguments

      > 2. Maybe loop content need need to be
      Fixed, thanks

  6. Apr 24, 2012

    I find a "loopbody" as a little ugly artificial strut. We define an operation with a collection in a functional (declarative) way and every collection may hide their loop implementation, and in general case a collection does not guarantee a sequential order of iterating. An good example is parallel collections.

    Thus it will be good to define two methods for collection iteration:

    which iterates in collection-specific way without possibility of breaking. And another one:

    which iterates a collection sequentially. A Closure must return true to continue iteration or false to break it.

    1. Apr 24, 2012

      This doesn't mean that we should not support break/continue for the situations where iteration is actually sequential.

  7. Jul 27, 2012

    You say, that "return" returns from "foo" function, but how does it work?? Is it works, because forEach is inline function ??
    If i remove inline modifier then behavior changes?

    1. Jul 27, 2012

      If you remove the "inline" modifier, this code does not compile any more.

  8. Jul 09, 2013

    I can remember the college time, that we were taught to avoid jump (break to label) because it is an evil. I don't know if Kotlin really needs this feature or not, but frankly, to me its a bit scary and hard to trace. 

  9. Apr 03, 2014

    I find deep nested braces to be difficult to keep track of.  In Java we uses the coding style of "early exit" to check preconditions and exit if they are not met, like 

    In kotlin this does not work, because there is no way to exit a block, the "return@" syntax does not appear to work in m7

    What about using "break" for this, and even allowing break to return values, in the case of a block returning something other than Unit

    1. Apr 03, 2014

      You can use return@forEach, but the current version has a limitation: you need to specify the return type of the lambda explicitly:

      items.forEach{ (item): Unit -> 
        if( item.getData() == null ) { 
          return@forEach; 
        } 
        if ( item.getStatus() != runnable ) { 
          return; 
        } 
       
        //do work 
      }

      P.S. Just in case: semicolons are optional