Icon

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
Icon

The documentation for Kotlin is now located on the new site. This page is kept for historical reasons

If expression

In Kotlin, if is an expression, i.e. it returns a value. Therefore there is not ternary operator (condition ? then : else), because ordinary if works fine in this role. Consider the following examples:

// Traditional usage 
var max = a 
if (a < b) 
  max = b 
 
// With else 
var max : Int 
if (a > b) 
  max = a 
else 
  max = b 
 
// As expression 
val max = if (a > b) a else b

If branches can be blocks, and the last expression is the value of a block:

val max = if (a > b) { 
    print("Choose a") 
    a 
  } 
  else { 
    print("Choose b") 
    b 
  }

When if has only one branch, or one of its branches results in Unit, it's type is Unit.

See the grammar for if here.

When expression

When replaces the switch operator of C-like languages. In the simplest form it looks like this:

when (x) { 
  1 -> print("x == 1") 
  2 -> print("x == 2") 
  else -> { // Note the block 
    print("x is neither 1 nor 2") 
  } 
}

When matches its argument against all branches consequently until some branch condition is satisfied. When is an expression and results in satisfied branch's right hand side. If some of its branches return result in a value of type Unit, the whole expression has type Unit.
Note that the else branch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions.

If many cases should be handled in the same way, the branch conditions may be combined with a comma:

when (x) { 
  0, 1 -> print("x == 0 or x == 1") 
  else -> print("otherwise") 
}

We can use arbitrary expressions (not only constants) as branch conditions:

when (x) { 
  parseInt(s) -> print("s encodes x") 
  else -> print("s does not encode x") 
}

One can also check a value for being in or !in a range:

when (x) { 
  in 1..10 -> print("x is in the range") 
  !in 10..20 -> print("x is outside the range") 
  else -> print("none of the above") 
}


When can also be used as a replacement for an if-else-if chain. If no argument is supplied, the branch conditions are simply boolean expressions, and a branch is executed when its condition is true:

when { 
  x.isOdd() -> print("x is odd") 
  x.isEven() -> print("x is even") 
  else -> print("x is funny") 
}

Continue inside when

Inside when expressions, continue jumps to the next branch condition, if any:

when (x) { 
  in 1..100 -> 
    if (x.isOdd()) 
      continue // Jump to the next branch, i.e. '3, 101 -> ...' 
    else 
      print("Even between 1 and 100") 
  3, 101 -> print("3 or 101") 
  1000 -> 
continue
 // Error: continue is not allowed in the last branch 
}

This mechanism replaces the concept of guards available in other languages. I.e. in Scala one has guard if expressions in match (that corresponds to when):

This can be rewritten in Kotlin with as follows:

when(term) { 
  is Fun -> { if (tem.v != term.body) continue; print(x) } 
  else -> print("Nope!") 
}

See Returns and jumps for more information about continue.

See the grammar for when here.

Continue in when is not implemented yet

Icon

See the corresponding issue


For loop

For loop iterates through anything that provides an iterator. The syntax is as follows:

for (item in collection) 
  print(item)

The body can be a block.

for (item : Int in ints) { 
  // ... 
}

As mentioned before, for iterates through anything that provides and iterator, i.e.

  1. has an instance- or extension-function iterator(), whose return type
  2. has an instance- or extension-function next(), and
  3. has an instance- or extension-function hasNext() that returns Boolean.

If you want to iterate through an array or list with an index, you can do it this way:

for (i in array.indices) 
  print(array[i])

Note that this "iteration through a range" is compiled down to optimal implementation with no extra objects created.

See the grammar for for here.

While and do..while loops

While and do..while work as usual:

while(x > 0) { 
  x-- 
} 
 
do { 
  val y = retrieveData() 
} while(y != null) // y is visible here!

See the grammar for while here.

Break and continue in loops

Kotlin supports traditional break and continue operators in loops. See more here Returns and jumps.

Try expression

See Exceptions for the details.

What's next

  • No labels

39 Comments

  1. Anonymous

    Please can we have the same syntax for arrays. An array is a collection. The compiler can figure it out. 

    Secondly, this would be huge, can we have multiple collections, iterated in parallel:

    The above should throw an exception if the sizes dont match, or fail to compile if the collections dont have a size. This would compile tho:

    1. Array is not the special case in Kotlin, so it'll with arrays. Parallel iteration can be expresses, for instance, with extension function to a tuple of collections. The code will look like this

      1. Could you provide a working example?

        1. The library code for this is not there yet, sorry. The main idea is this:

          class Pair<A, B>(val a : A, val b : B) 
           
          fun <A, B> Pair<out Iterable<A>, out Iterable<B>>.forEach(f : (A, B) -> Unit) { 
            val ia = a.iterator() 
            val ib = b.iterator() 
            while (ia.hasNext() && ib.hasNext()) { 
              val va = ia.next() 
              val vb = ib.next() 
              f(va, vb) 
            } 
          } 
           
          fun test() { 
            val a = list(1, 2, 3) 
            val b = list("1", "2", "3") 
            Pair(a, b).forEach { a, b -> 
              println("a = $a, b = $b") 
            } 
          }
  2. Anonymous

    Since you permit "in" in "when" statements, perhaps there is also a case for other binary comparison operators? e.g.

    or can this be somehow expressed with ranges already (open upper/lower boundaries)?

    1. As can be seen in your example, the code becomes rather ugly this way with all those "< 1 =>" and stuff... And you can't have + there, for it has a prefix form... So, we are not sure what's good here

      1. Anonymous

        Yes, I tried writing this down with "<=", and it looks downright ugly. Having open-ended ranges solve this much neater - something like "(1..)" and "(..100)"; or perhaps "(1..)" and "(..100)", since you tend to use "*"  for wildcards:

        1. If you need comparisons in particular, we have this (may be dropped later):

          when (x) { 
              .lessThan(0) => ... 
              in 1..10 => ... 
              .greaterThan(10) => ... 
            } 
           
            inline fun Int.lessThan(y : Int) = this < y 
            inline fun Int.greaterThan(y : Int) = this > y
  3. Anonymous

    I'm not entirely sure from the examples provided, but it looks like "continue" is a jump statement rather than an expression. Does this mean that it cannot be used in expression contexts at all? e.g. can I write:

    It would be nice if the above was valid. Of course, this begs the question of what the type of "continue" then is, since it now has to be an expression. It would require introducing a bottom type to the type system. But then you could also give the same treatment to "break" and "return", so that crazy things like "1 + break @foo" become possible. :)

    On the other hand, an even niftier feature would be to have something like expression "continue", but with the ability to further modify the value in our branch. Something like <xsl:next-match/> from XSTL, basically:

    1. continue is a legitimate expression of type Nothing. Your first example is perfectly OK in Kotlin.

  4. Anonymous

    I applaud your decision of making Kotlin control structures expressions, but have you considered dropping the parentheses around the predicate rather than keeping them mandatory as in the C/C++/Java heritage? For one thing, for expressions would flow more naturally, as in

    And by making the curly braces mandatory instead of the parentheses, you would on one move remove the infamous dangling else problem and a common source of errors when extending a one-line control structure without curly braces. I think that alone would help your language a little further on the way towards industrial use.

    Of course, syntax familiarity might be a more important criterion...

    1. One problem with this is the if expression that replaces the ternary operator:

      val x = if (y > 0) 1 else 2

      With curly braces that would be strange

  5. Please add a way to getting the index in for loops without having to create one explicitly. For example:

    Or for maps:

    In current java, it's very annoying to always write code like this:

    1. Currently you can say:

      for (i in array.indices) { 
        ... 
      }
      1. I know. But if I use a for loop to iterate over a collection, in many cases need both: The current value and the current index.

        An example is the "Index of Maximum" problem in your web demo: You need both the current value and the current index in the loop to solve it.

        Now you can of course use a counter variable to get the index or iterate over the index and fetch the current value from the array, but since it's a very common case (I suspect I need both the current value and the index it in around 20% of all for loops over collections) it would be nice to have language support for it. The compiler can easily insert the required code only if it's used.

        Also the 'manual' version have all disadvantages:

        • The solution above needs to declare the index-variable outside the for() which pollutes the outer scope with a variable which is only needed inside the loop.
        • incrementing the index manually can lead to errors if you use continue in the loop
        • you can't declare the index variable as val

        And if you just iterate over indices and use array[i] to get the value this only works well for array lists, for other kinds of collections it can be very inefficient.

        Of course this could also solved by writing a each function which gives both value and index, but since there is a for loop in the language, I think it should be as usable as possible.

        1. I suspect I need both the current value and the index it in around 20% of all for loops over collections

          I'd say that even 5% would be an exaggeration. When we figure out some really pretty syntax for indexed loops, we'll be happy to support it, but so far nothing seems goof enough.

          For the time being, I'd suggest one of the two solutions:

          forWithIndex(collection) {i, v -> 
            print("index = $i, value = $v") 
          }

          or

          for (iv in collection.indexed) { 
            print("index = ${iv.index}, value = ${iv.value}") 
          }
          1. Would you like the following Syntax?

            v and i should be immutable vals inside the loop.

            1. The idea is interesting, but I'm not totally convinced it adds enough value to be hard-coded in the language

      2. An alternative idea for the syntax would be to use loop labels to get the current index or a boolean to return true if index==0:

      3. Having the object and it's indices might not be the first use case for loops, but it feels to me like it is the second use case (for arrays and arrayLists).
        Is the 5% figure an actual computed stats on a big code base ? (say, on the kotlin coded stuff at intellij if you have tools to compute such statistics ?)
        In my code, I have quite a lot of

        Had we a syntax like

        We could write one liners instead of 3-liners like

        1. for ((i, v) in array.withIndices()) { 
             // ... 
          }
  6. "Note that the else branch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions."

    This is a real gem. It implies that the Kotlin compiler can determine whether you have enumerated all conditions of enum types. So now we can safely add new enum values and the compiler helps us to identify the gaps.

    Great work!

  7. Kotlin is looking very interesting indeed...

    I don't particularly want more keywords, but a very useful construct is: until (x) { } meaning the same as while (!x) { } . Found in some languages but never made it into the C family. This is usually more natural than 'while', simply because loops are often waiting for a condition to be satisfied, instead of waiting for a failed condition to disappear.

    A trivial example:

    Equally useful is do { } until (x) instead of do { } while (!x).

    1. Thanks for your suggestion. I don't think these constructs are useful enough to be introduced: they make the language bigger and break the tradition, and the benefit is recognized by negligibly few people.

  8. Hello. I've just read this article and trying when-statement myself.

    Could you please explain this:

    "
    This can be rewritten in Kotlin with as follows:

    "

    What is "Fun#(..."? Is it a tuple or special syntax to match properties of the Fun object?
    I failed to compile that code with several errors: "x is undefined" and "expected -> or when" on the '#' symbol.

    1. It's an outdated piece of documentation. Fixed now.

  9. Is there any way to check against function type in "when" statement?

    i.e.:

    1. Syntax is different: (Int, Int) -> Int ("->" instead of ":"), but the compiler won't let you write such checks because they correspond to "it is Function2<Int, Int, Int>", and checks for generic types are infeasible at runtime (due to erasure).

  10. Compile Error: var(and val) on loop parameter is not allowed.

  11. Would it be possible (library function ?) to have something like 

    val a : Array<String>? = null 
     
    for (string in array) { 
     
    }

    instead of 

    val a : Array<String>? = null 
     
    if (array != null) for (string in array) { 
     
    }

    Shouldn't Iterating be possible for an object with an iterator or for an object that has an iterator when it is not null ?

    Would it make sense to have this in a library or in the language ? 

    1. This is debatable. We decided not to have this behaviour by default, but I think there is an orEmpty() function:

      for (a in arr.orEmpty()) {...}
  12. I love "when", it really helps writing concise code.
    But I sometimes wish there was a way to execute some code between tests like this

    When you have lot's of tests with some conditionnal code execution in between, you have to go back to if then else and it gets quickly messy although the structure of the tests is quite simple (not nested)

    Is there something like that in Kotlin ?

    1. You can write it like this:

      when { 
       s =="is" ->  0 
      } 
      t = s.toUpper() 
      when { 
       t == "THIS" ->  1 
       t == "HOPE" && s="less?" ->  2 
      ... 
      else -> 666 
      }

      No if-else required

  13. I noticed that kotlin is moving away from iterators to streams (=lazy iterators).

    Will the containers (like arraylist) that have a iterator() method at one point implement Stream<T> ?
    At this point, the syntax looks a bit verbose :

    What are the average performance benefits of using streams/iterators over copy, is there a point (with too many composition) where these benefits disappear ?

    Do streams/iterators in kotlin take their inspiration from stuff like this http://zao.se/~zao/boostcon/09/2009_presentations/wed/iterators-must-go.pdf ?

    1. It's actually

      for (s in arrayListA.stream().map {it.string} + arrayListB.stream().map {it.string}) { 
        // ... 
      }

      Collections will not implement Stream or the example above will be impossible.
      You need to put in VERY many compositions to outweigh copying a list of a few million elements.
      Streams in Kotlin are inspired by streams in Java and an obvious need in laziness

      1. Many thanks for the answer. I have been developing for Android for so long that I forgot about Java 8.
        Also, I had a look at the java streams and it will make me a better developer.

        I have one last question :

        in Kotlin and Idea configured with Java 7 /android, we can already use stream()... but not parallelStream().... (maybee it is with Java 8 + kotlin ?)
        So, I'm a bit confused by what features are available or not for development with kotlin on the JVM and on Android
        Doesn't the availability of features depends on the JVM/Android version ?

        1. Kotlin does not use Java 8 streams at the moment (we only have our own simplistic Stream interface), so parallelStream() is not available on any platform. When we support it in the standard library, it will be available for Java 8, but I'm not sure whether it is practical to backport streams to earlier Java versions.