207 lines
5.5 KiB
Plaintext
207 lines
5.5 KiB
Plaintext
{anchor:If}
|
|
|
|
h3. 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:
|
|
|
|
{jet}
|
|
// 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
|
|
{jet}
|
|
|
|
*If* branches can be blocks, and the last expression is the value of a block:
|
|
{jet}
|
|
val max = if (a > b) {
|
|
print("Choose a")
|
|
a
|
|
}
|
|
else {
|
|
print("Choose b")
|
|
b
|
|
}
|
|
{jet}
|
|
|
|
When *if* has only one branch, or one of its branches results in [{{Unit}}|Functions#Unit], it's type is [{{Unit}}|Functions#Unit].
|
|
|
|
See the grammar for *if* [here|Grammar#if].
|
|
|
|
{anchor:When}
|
|
|
|
h3. When expression
|
|
|
|
*When* replaces the *switch* operator of *C*\-like languages. In the simplest form it looks like this:
|
|
{jet}
|
|
when (x) {
|
|
1 -> print("x == 1")
|
|
2 -> print("x == 2")
|
|
else -> { // Note the block
|
|
print("x is neither 1 nor 2")
|
|
}
|
|
}
|
|
{jet}
|
|
|
|
*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}}|Functions#Unit], the whole expression has type [{{Unit}}|Functions#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:
|
|
{jet}
|
|
when (x) {
|
|
0, 1 -> print("x == 0 or x == 1")
|
|
else -> print("otherwise")
|
|
}
|
|
{jet}
|
|
|
|
We can use arbitrary expressions (not only constants) as branch conditions:
|
|
{jet}
|
|
when (x) {
|
|
parseInt(s) -> print("s encodes x")
|
|
else -> print("s does not encode x")
|
|
}
|
|
{jet}
|
|
|
|
One can also check a value for being *in* or *\!in* a [range|Ranges]:
|
|
{jet}
|
|
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")
|
|
}
|
|
{jet}
|
|
|
|
*When*\-expressions support [pattern matching|Pattern matching] through {{is}} and {{\!is}}:
|
|
{jet}
|
|
when (tuple) {
|
|
is #(1, 2) -> ...
|
|
is #(val a, 3) -> print(a) // binding a to the first element of the tuple
|
|
!is #(*, 1100) -> ...
|
|
else -> ...
|
|
}
|
|
{jet}
|
|
We do not expand on the pattern matching here. For details, look at [this page|Pattern matching].
|
|
|
|
{anchor:bare-when}
|
|
*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:
|
|
{jet}
|
|
when {
|
|
x.isOdd() -> print("x is odd")
|
|
x.isEven() -> print("x is even")
|
|
else -> print("x is funny")
|
|
}
|
|
{jet}
|
|
|
|
{anchor:continue-when}
|
|
h4. Continue inside {{when}}
|
|
|
|
Inside *when* expressions, *continue* jumps to the next branch condition, if any:
|
|
{jet}
|
|
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 -> <error desc="'continue' is not allowed in the last branch">continue</error> // Error: continue is not allowed in the last branch
|
|
}
|
|
{jet}
|
|
|
|
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*):
|
|
{code:Scala}
|
|
// Scala
|
|
term match {
|
|
case Fun(x, Var(y)) if x == y -> print(x)
|
|
case _ -> print("Nope!")
|
|
}
|
|
{code}
|
|
This can be rewritten in [Kotlin] with as follows:
|
|
{jet}
|
|
when(term) {
|
|
is Fun#(val x, Var#(val y)) -> { if (x != y) continue; print(x) }
|
|
else -> print("Nope!")
|
|
}
|
|
{jet}
|
|
See [Returns and jumps] for more information about *continue*.
|
|
|
|
See the grammar for *when* [here|Grammar#when].
|
|
See also [Pattern matching].
|
|
|
|
{note:title=Continue in when is not implemented yet}See the corresponding [issue|http://youtrack.jetbrains.com/issue/KT-771]{note}
|
|
|
|
{anchor:Loops}
|
|
{anchor:For}
|
|
h3. For loop
|
|
|
|
*For* loop iterates through anything that provides an _iterator_. The syntax is as follows:
|
|
{jet}
|
|
for (item in collection)
|
|
print(item)
|
|
{jet}
|
|
|
|
One can specify a type and *val* or *var* for the loop variable. The body can be a block.
|
|
{jet}
|
|
for (val item : Int in ints) {
|
|
// ...
|
|
}
|
|
{jet}
|
|
|
|
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
|
|
# either
|
|
## a property {{hasNext}} of type {{Boolean}}, or
|
|
## a function {{hasNext()}} that returns {{Boolean}}.
|
|
|
|
If you want to iterate through an [array|Basic types#Arrays] or list with an index, you can do it this way:
|
|
{jet}
|
|
for (i in array.indices)
|
|
print(array[i])
|
|
{jet}
|
|
Note that this "iteration through a range" is compiled down to optimal implementation with no extra objects created.
|
|
|
|
See the grammar for *for* [here|Grammar#for].
|
|
|
|
{anchor:while}
|
|
|
|
h3. While and do..while loops
|
|
|
|
*While* and *do*..*while* work as usual:
|
|
{jet}
|
|
while(x > 0) {
|
|
x--
|
|
}
|
|
|
|
do {
|
|
val y = retrieveData()
|
|
} while(y != null) // y is visible here!
|
|
{jet}
|
|
|
|
See the grammar for *while* [here|Grammar#while].
|
|
|
|
h3. Break and continue in loops
|
|
|
|
[Kotlin] supports traditional *break* and *continue* operators in loops. See more here [Returns and jumps].
|
|
|
|
h3. Try expression
|
|
|
|
See [Exceptions] for the details.
|
|
|
|
h3. What's next
|
|
|
|
* [Function literals]
|
|
* [Returns and jumps]
|
|
* [Ranges]
|
|
* [This expressions]
|
|
* [Tuples]
|
|
* [Type casts] |