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 bIf 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 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)One can specify a type and val or var for the loop variable. The body can be a block.
for (val item : Int in ints) { // ... }As mentioned before, for iterates through anything that provides and iterator, i.e.
- has an instance- or extension-function iterator(), whose return type
- has an instance- or extension-function next(), and
- 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.

27 Comments
comments.show.hideJul 20, 2011
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:
Jul 20, 2011
Maxim Shafirov
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
May 21, 2012
Andrey Abakumov
Could you provide a working example?
May 23, 2012
Andrey Breslav
The library code for this is not there yet, sorry. The main idea is this:
classPair<A,B>(vala:A,valb:B)fun<A,B>Pair<outIterable<A>,outIterable<B>>.forEach(f:(A,B)->Unit){valia=a.iterator()valib=b.iterator()while(ia.hasNext()&&ib.hasNext()){valva=ia.next()valvb=ib.next()f(va,vb)}}funtest(){vala=list(1,2,3)valb=list("1","2","3")Pair(a,b).forEach{a,b->println("a =$a, b =$b")}}Jul 21, 2011
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)?
Jul 21, 2011
Andrey Breslav
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
Jul 21, 2011
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:
Jul 21, 2011
Andrey Breslav
If you need comparisons in particular, we have this (may be dropped later):
when(x){.lessThan(0)=>...in1..10=>....greaterThan(10)=>...}inlinefunInt.lessThan(y:Int)=this<yinlinefunInt.greaterThan(y:Int)=this>yJul 21, 2011
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:
Jul 21, 2011
Andrey Breslav
continue is a legitimate expression of type Nothing. Your first example is perfectly OK in Kotlin.
Jul 25, 2011
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...
Jul 27, 2011
Andrey Breslav
One problem with this is the if expression that replaces the ternary operator:
valx=if(y>0)1else2With curly braces that would be strange
Feb 03, 2012
Karsten Wagner
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:
Feb 03, 2012
Andrey Breslav
Currently you can say:
for(iinarray.indices){...}Feb 03, 2012
Karsten Wagner
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:
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.
Feb 03, 2012
Andrey Breslav
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(ivincollection.indexed){print("index =${iv.index}, value =${iv.value}")}Mar 05, 2012
Pascal Brain
Would you like the following Syntax?
v and i should be immutable vals inside the loop.
Mar 07, 2012
Andrey Breslav
The idea is interesting, but I'm not totally convinced it adds enough value to be hard-coded in the language
Feb 03, 2012
Karsten Wagner
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:
Apr 29, 2012
Mark Platvoet
"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!
May 01, 2012
Andrey Breslav
Thanks
Oct 08, 2012
Jonathan
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).
Oct 08, 2012
Andrey Breslav
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.
May 16, 2013
Alexey Pomelov
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.
May 16, 2013
Andrey Breslav
It's an outdated piece of documentation. Fixed now.
Jun 08, 2013
Alexey Pomelov
Is there any way to check against function type in "when" statement?
i.e.:
Jun 08, 2013
Andrey Breslav
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).