diff --git a/docs/topics/advent-of-code.md b/docs/topics/advent-of-code.md
index 2b223e985b6..80dbefae011 100644
--- a/docs/topics/advent-of-code.md
+++ b/docs/topics/advent-of-code.md
@@ -230,7 +230,7 @@ or watch the video:
### Day 4: Passport processing
-Apply the [`when`](control-flow.md#when-expression) expression and explore different ways of how to validate the input:
+Apply the [`when`](control-flow.md#when-expressions-and-statements) expression and explore different ways of how to validate the input:
utility functions, working with ranges, checking set membership, and matching a particular regular expression.
* Read the puzzle description on [Advent of Code](https://adventofcode.com/2020/day/4)
diff --git a/docs/topics/basic-syntax.md b/docs/topics/basic-syntax.md
index 88ebbe3e92c..f56133c4c76 100644
--- a/docs/topics/basic-syntax.md
+++ b/docs/topics/basic-syntax.md
@@ -437,7 +437,7 @@ fun main() {
```
{kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-basic-syntax-when-expression"}
-See [when expression](control-flow.md#when-expression).
+See [when expressions and statements](control-flow.md#when-expressions-and-statements).
## Ranges
diff --git a/docs/topics/control-flow.md b/docs/topics/control-flow.md
index 6b3e692d319..33d4d4deeb3 100644
--- a/docs/topics/control-flow.md
+++ b/docs/topics/control-flow.md
@@ -27,10 +27,12 @@ fun main() {
// You can also use `else if` in expressions:
val maxLimit = 1
val maxOrLimit = if (maxLimit > a) maxLimit else if (a > b) a else b
-
- //sampleEnd
+
println("max is $max")
+ // max is 3
println("maxOrLimit is $maxOrLimit")
+ // maxOrLimit is 3
+ //sampleEnd
}
```
{kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="if-else-if-kotlin"}
@@ -50,33 +52,125 @@ val max = if (a > b) {
If you're using `if` as an expression, for example, for returning its value or
assigning it to a variable, the `else` branch is mandatory.
-## When expression
+## When expressions and statements
+
+`when` is a conditional expression that runs code based on multiple possible values or conditions. It is
+similar to the `switch` statement in Java, C, and similar languages. For example:
+
+```kotlin
+fun main() {
+ //sampleStart
+ val x = 2
+ when (x) {
+ 1 -> print("x == 1")
+ 2 -> print("x == 2")
+ else -> print("x is neither 1 nor 2")
+ }
+ // x == 2
+ //sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-conditions-when-statement"}
+
+`when` matches its argument against all branches sequentially until some branch condition is satisfied.
+
+You can use `when` in a few different ways. Firstly, you can use `when` either as an **expression** or as a **statement**.
+As an expression, `when` returns a value for later use in your code. As a statement, `when` completes an action
+without returning anything of further use:
+
+
+
+ Expression |
+ Statement |
+
+
+
+
+```kotlin
+// Returns a string assigned to the
+// text variable
+val text = when (x) {
+ 1 -> "x == 1"
+ 2 -> "x == 2"
+ else -> "x is neither 1 nor 2"
+}
+```
-`when` defines a conditional expression with multiple branches. It is similar to the `switch` statement in C-like languages.
-Its simple form looks like this.
+ |
+
```kotlin
+// Returns nothing but triggers a
+// print statement
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
- else -> {
- print("x is neither 1 nor 2")
- }
+ else -> print("x is neither 1 nor 2")
}
```
-`when` matches its argument against all branches sequentially until some branch condition is satisfied.
+ |
+
+
-`when` can be used either as an expression or as a statement. If it is used as an expression, the value
-of the first matching branch becomes the value of the overall expression. If it is used as a statement, the values of
-individual branches are ignored. Just like with `if`, each branch can be a block, and its value
-is the value of the last expression in the block.
+Secondly, you can use `when` with or without a subject. Whether you use a subject with `when` or not, your expression or
+statement behaves the same. We recommend using `when` with a subject when possible, as it makes your code easier to read
+and maintain by clearly showing what you're checking.
-The `else` branch is evaluated if none of the other branch conditions are satisfied.
+
+
+ With subject x |
+ Without subject |
+
+
+
-If `when` is used as an _expression_, the `else` branch is mandatory,
-unless the compiler can prove that all possible cases are covered with branch conditions,
-for example, with [`enum` class](enum-classes.md) entries and [`sealed` class](sealed-classes.md) subtypes).
+```kotlin
+when(x) { ... }
+```
+
+ |
+
+
+```kotlin
+when { ... }
+```
+
+ |
+
+
+
+Depending on how you use `when`, there are different requirements for whether you need to cover all possible cases in your
+branches.
+
+If you use `when` as a statement, you don't have to cover all possible cases. In this example, some cases aren't covered,
+so nothing happens. However, no error occurs:
+
+```kotlin
+fun main() {
+ //sampleStart
+ val x = 2
+ when (x) {
+ // Not all cases are covered
+ 1 -> print("x == 1")
+ 2 -> print("x == 2")
+ }
+ // x == 2
+ //sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-when-statement"}
+
+In a `when` statement, the values of individual branches are ignored. Just like with `if`, each branch can be a block,
+and its value is the value of the last expression in the block.
+
+If you use `when` as an expression, you have to cover all possible cases. In other words, it must be _exhaustive_.
+The value of the first matching branch becomes the value of the overall expression. If you don't cover all cases,
+the compiler throws an error.
+
+If your `when` expression has a subject, you can use an `else` branch to make sure that all possible cases are covered, but
+it isn't mandatory. For example, if your subject is a `Boolean`, [`enum` class](enum-classes.md), [`sealed` class](sealed-classes.md),
+or one of their nullable counterparts, you can cover all cases without an `else` branch:
```kotlin
enum class Bit {
@@ -84,37 +178,27 @@ enum class Bit {
}
val numericValue = when (getRandomBit()) {
+ // No else branch is needed because all cases are covered
Bit.ZERO -> 0
Bit.ONE -> 1
- // 'else' is not required because all cases are covered
}
```
-In `when` _statements_, the `else` branch is mandatory in the following conditions:
-* `when` has a subject of a `Boolean`, [`enum`](enum-classes.md),
-or [`sealed`](sealed-classes.md) type, or their nullable counterparts.
-* branches of `when` don't cover all possible cases for this subject.
+If your `when` expression **doesn't** have a subject, you **must** have an `else` branch or the compiler throws an error.
+The `else` branch is evaluated when none of the other branch conditions are satisfied:
```kotlin
-enum class Color {
- RED, GREEN, BLUE
-}
-
-when (getColor()) {
- Color.RED -> println("red")
- Color.GREEN -> println("green")
- Color.BLUE -> println("blue")
- // 'else' is not required because all cases are covered
-}
-
-when (getColor()) {
- Color.RED -> println("red") // no branches for GREEN and BLUE
- else -> println("not red") // 'else' is required
+when {
+ a > b -> "a is greater than b"
+ a < b -> "a is less than b"
+ else -> "a is equal to b"
}
```
+`when` expressions and statements offer different ways to simplify your code, handle multiple conditions, and perform
+type checks.
-To define a common behavior for multiple cases, combine their conditions in a single line with a comma:
+You can define a common behavior for multiple cases by combining their conditions in a single line with a comma:
```kotlin
when (x) {
@@ -123,7 +207,7 @@ when (x) {
}
```
-You can use arbitrary expressions (not only constants) as branch conditions
+You can use arbitrary expressions (not only constants) as branch conditions:
```kotlin
when (x) {
@@ -132,7 +216,7 @@ when (x) {
}
```
-You can also check a value for being `in` or `!in` a [range](ranges.md) or a collection:
+You can also check whether a value is or isn't contained in a [range](ranges.md) or collection via the `in` or `!in` keywords:
```kotlin
when (x) {
@@ -143,9 +227,9 @@ when (x) {
}
```
-Another option is checking that a value `is` or `!is` of a particular type. Note that,
-due to [smart casts](typecasts.md#smart-casts), you can access the methods and properties of the type without
-any extra checks.
+Additionally, you can check that a value is or isn't a particular type via the `is` or `!is` keywords. Note that,
+due to [smart casts](typecasts.md#smart-casts), you can access the member functions and properties of the type without
+any additional checks.
```kotlin
fun hasPrefix(x: Any) = when(x) {
@@ -154,8 +238,8 @@ fun hasPrefix(x: Any) = when(x) {
}
```
-`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:
+You can use `when` as a replacement for an `if`-`else` `if` chain.
+If there's no subject, the branch conditions are simply boolean expressions, and a branch is run when its condition is true:
```kotlin
when {
@@ -165,7 +249,7 @@ when {
}
```
-You can capture *when* subject in a variable using following syntax:
+You can capture the subject in a variable by using the following syntax:
```kotlin
fun Request.getBody() =
@@ -175,7 +259,7 @@ fun Request.getBody() =
}
```
-The scope of variable introduced in *when* subject is restricted to the body of this *when*.
+The scope of a variable introduced as the subject is restricted to the body of the `when` expression or statement.
## For loops
@@ -208,11 +292,12 @@ To iterate over a range of numbers, use a [range expression](ranges.md):
fun main() {
//sampleStart
for (i in 1..3) {
- println(i)
+ print(i)
}
for (i in 6 downTo 0 step 2) {
- println(i)
+ print(i)
}
+ // 1236420
//sampleEnd
}
```
@@ -227,8 +312,9 @@ fun main() {
val array = arrayOf("a", "b", "c")
//sampleStart
for (i in array.indices) {
- println(array[i])
+ print(array[i])
}
+ // abc
//sampleEnd
}
```
@@ -243,6 +329,9 @@ fun main() {
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
+ // the element at 0 is a
+ // the element at 1 is b
+ // the element at 2 is c
//sampleEnd
}
```
@@ -250,11 +339,11 @@ fun main() {
## While loops
-`while` and `do-while` loops execute their body continuously while their condition is satisfied.
+`while` and `do-while` loops process their body continuously while their condition is satisfied.
The difference between them is the condition checking time:
-* `while` checks the condition and, if it's satisfied, executes the body and then returns to the condition check.
-* `do-while` executes the body and then checks the condition. If it's satisfied, the loop repeats. So, the body of `do-while`
-executes at least once regardless of the condition.
+* `while` checks the condition and, if it's satisfied, processes the body and then returns to the condition check.
+* `do-while` processes the body and then checks the condition. If it's satisfied, the loop repeats. So, the body of `do-while`
+runs at least once regardless of the condition.
```kotlin
while (x > 0) {
diff --git a/docs/topics/keyword-reference.md b/docs/topics/keyword-reference.md
index 0fd0c163797..aaf0f265a56 100644
--- a/docs/topics/keyword-reference.md
+++ b/docs/topics/keyword-reference.md
@@ -21,19 +21,19 @@ The following tokens are always interpreted as keywords and cannot be used as id
- specifies the object being iterated in a [for loop](control-flow.md#for-loops).
- is used as an infix operator to check that a value belongs to [a range](ranges.md),
a collection, or another entity that [defines a 'contains' method](operator-overloading.md#in-operator).
- - is used in [when expressions](control-flow.md#when-expression) for the same purpose.
+ - is used in [when expressions](control-flow.md#when-expressions-and-statements) for the same purpose.
- marks a type parameter as [contravariant](generics.md#declaration-site-variance).
* `!in`
- is used as an operator to check that a value does NOT belong to [a range](ranges.md),
a collection, or another entity that [defines a 'contains' method](operator-overloading.md#in-operator).
- - is used in [when expressions](control-flow.md#when-expression) for the same purpose.
+ - is used in [when expressions](control-flow.md#when-expressions-and-statements) for the same purpose.
* `interface` declares an [interface](interfaces.md).
* `is`
- checks that [a value has a certain type](typecasts.md#is-and-is-operators).
- - is used in [when expressions](control-flow.md#when-expression) for the same purpose.
+ - is used in [when expressions](control-flow.md#when-expressions-and-statements) for the same purpose.
* `!is`
- checks that [a value does NOT have a certain type](typecasts.md#is-and-is-operators).
- - is used in [when expressions](control-flow.md#when-expression) for the same purpose.
+ - is used in [when expressions](control-flow.md#when-expressions-and-statements) for the same purpose.
* `null` is a constant representing an object reference that doesn't point to any object.
* `object` declares [a class and its instance at the same time](object-declarations.md).
* `package` specifies the [package for the current file](packages.md).
@@ -51,7 +51,7 @@ The following tokens are always interpreted as keywords and cannot be used as id
* `typeof` is reserved for future use.
* `val` declares a read-only [property](properties.md) or [local variable](basic-syntax.md#variables).
* `var` declares a mutable [property](properties.md) or [local variable](basic-syntax.md#variables).
- * `when` begins a [when expression](control-flow.md#when-expression) (executes one of the given branches).
+ * `when` begins a [when expression](control-flow.md#when-expressions-and-statements) (executes one of the given branches).
* `while` begins a [while loop](control-flow.md#while-loops) (a loop with a precondition).
## Soft keywords
@@ -153,7 +153,7 @@ Kotlin supports the following operators and special symbols:
* `->`
- separates the parameters and body of a [lambda expression](lambdas.md#lambda-expression-syntax).
- separates the parameters and return type declaration in a [function type](lambdas.md#function-types).
- - separates the condition and body of a [when expression](control-flow.md#when-expression) branch.
+ - separates the condition and body of a [when expression](control-flow.md#when-expressions-and-statements) branch.
* `@`
- introduces an [annotation](annotations.md#usage).
- introduces or references a [loop label](returns.md#break-and-continue-labels).
diff --git a/docs/topics/sealed-classes.md b/docs/topics/sealed-classes.md
index 85dff5c3626..9ad424df3b2 100644
--- a/docs/topics/sealed-classes.md
+++ b/docs/topics/sealed-classes.md
@@ -164,7 +164,7 @@ you can create subclasses in any source set between the `expect` and `actual` de
## Use sealed classes with when expression
-The key benefit of using sealed classes comes into play when you use them in a [`when`](control-flow.md#when-expression)
+The key benefit of using sealed classes comes into play when you use them in a [`when`](control-flow.md#when-expressions-and-statements)
expression.
The `when` expression, used with a sealed class, allows the Kotlin compiler to check exhaustively that all possible cases are covered.
In such cases, you don't need to add an `else` clause:
diff --git a/docs/topics/typecasts.md b/docs/topics/typecasts.md
index 3c5282e3410..fe8491c81b5 100644
--- a/docs/topics/typecasts.md
+++ b/docs/topics/typecasts.md
@@ -47,7 +47,7 @@ print(x.length) // x is automatically cast to String
### Control flow
-Smart casts work not only for `if` conditional expressions but also for [`when` expressions](control-flow.md#when-expression)
+Smart casts work not only for `if` conditional expressions but also for [`when` expressions](control-flow.md#when-expressions-and-statements)
and [`while` loops](control-flow.md#while-loops):
```kotlin
diff --git a/docs/topics/whatsnew13.md b/docs/topics/whatsnew13.md
index 32a8fc6c136..47560d71ecb 100644
--- a/docs/topics/whatsnew13.md
+++ b/docs/topics/whatsnew13.md
@@ -146,7 +146,7 @@ fun Request.getBody() =
```
While it was already possible to extract this variable just before `when` , `val` in `when` has its scope properly restricted
-to the body of `when`, and so preventing namespace pollution. [See the full documentation on `when` here](control-flow.md#when-expression).
+to the body of `when`, and so preventing namespace pollution. [See the full documentation on `when` here](control-flow.md#when-expressions-and-statements).
## @JvmStatic and @JvmField in companions of interfaces
diff --git a/docs/topics/whatsnew1530.md b/docs/topics/whatsnew1530.md
index 6ced83aed5e..a6b41372b01 100644
--- a/docs/topics/whatsnew1530.md
+++ b/docs/topics/whatsnew1530.md
@@ -32,7 +32,7 @@ and type inference:
>
{style="warning"}
-An _exhaustive_ [`when`](control-flow.md#when-expression) statement contains branches for all possible types or values of its subject or for some types plus an `else` branch. In other words, it covers all possible cases.
+An _exhaustive_ [`when`](control-flow.md#when-expressions-and-statements) statement contains branches for either all possible types or values of its subject, or for certain types and includes an `else` branch to cover any remaining cases.
We're planning to prohibit non-exhaustive `when` statements soon to make the behavior consistent with `when` expressions. To ensure smooth migration, you can configure the compiler to report warnings about non-exhaustive `when` statements with a sealed class or a Boolean. Such warnings will appear by default in Kotlin 1.6 and will become errors later.
diff --git a/docs/topics/whatsnew16.md b/docs/topics/whatsnew16.md
index d78090f885f..943318bff51 100644
--- a/docs/topics/whatsnew16.md
+++ b/docs/topics/whatsnew16.md
@@ -21,7 +21,7 @@ It also includes various type inference improvements and support for annotations
### Stable exhaustive when statements for enum, sealed, and Boolean subjects
-An _exhaustive_ [`when`](control-flow.md#when-expression) statement contains branches for all possible types or values of
+An _exhaustive_ [`when`](control-flow.md#when-expressions-and-statements) statement contains branches for all possible types or values of
its subject, or for some types plus an `else` branch. It covers all possible cases, making your code safer.
We will soon prohibit non-exhaustive `when` statements to make the behavior consistent with `when` expressions.
diff --git a/docs/topics/whatsnew20.md b/docs/topics/whatsnew20.md
index f67095873c5..1e9d742b8e7 100644
--- a/docs/topics/whatsnew20.md
+++ b/docs/topics/whatsnew20.md
@@ -1526,7 +1526,7 @@ Since Kotlin 2.0.0, the following DSLs for specifying compiler options are depre
* The `kotlinOptions` DSL from the `KotlinCompile` interface that implements all Kotlin compilation tasks. Use
`KotlinCompilationTask` instead.
-* The `compilerOptions` property with the `HasCompilerOptions` type from the `KotlinCompiation` interface. This DSL was
+* The `compilerOptions` property with the `HasCompilerOptions` type from the `KotlinCompilation` interface. This DSL was
inconsistent with other DSLs and configured the same `KotlinCommonCompilerOptions` object as `compilerOptions` inside
the `KotlinCompilation.compileTaskProvider` compilation task, which was confusing.