Kotlin If, When and While - mariamaged/Java-Android-Kotlin GitHub Wiki

Kotlin - If, When and While

  • if is nearly ubiquitous in computer programming.
Java
if(i > 10) {
	// Do something.
}
else {
	// Do something else.
}
JavaScript
if(i > 10) {
	// Do something.
}
else {
	// Do something else.	
}
// Yes, it is the same as Java syntax.
Ruby
if(i > 10) 
	# Do something.
else
	# Do something.
end	
Kotlin
val i = 3
if(i > 10) {
	println("Something")
}
else {
	println("Something else")
}
  1. For single-line conditional work, you can skip the braces.
val i = 3
if(i > 10) println("Something") else println("Something else")
  1. It also supports else if in addition to a simple else:
val i = 3
if(i > 10) println("Something")
else if(i > 2) println("Something else")
else println("And now for something completely different")

When

when is distinctive.

when is powerful.

when is used a lot in Kotlin programming.

What We Do Elsewhere

  • The closest analogy to when in Java is the switch statement.
  • Here, depending on the value of foo , we evaluate one set of statement that follows the matching case (or the default statements, if there are no matches).
switch(foo) {
case 1:
	  // Do something.
	  break;
case 2: 
	  // Do something else.
	  break;
default:
	  // Like, whatever.
}
  • Javascript also has a switch, with same syntax as Java.
  • Ruby uses case, and it is the closest of the three in terms of matching the power of when.
case foo
	when 1 
		# Do something.
	when 2
		# Do something else.
    else
	    # Like, whatever.
end

The Basic Use of when

The most commonly-seen of when looks like a Java/ JavaScript switch or Ruby case, when you supply a value for comparison and set up different branch conditions to test against that value:

val i = 3

when(i)  {
	1 -> println("Something")
	2 -> println("Something else")
	else -> println("And now for something completely different")
}
  • Each branch has a value.
  • That is compared to an input.
     
  • The first match has its statement or block evaluated, and everything else is skipped.
    • If there are no matches, the else statement or block is evaluated.
  • The -> separates the branch comparison to the stuff that should be executed if that branch comparison is met.

In this case, the output is:

And now for something completely different.

  • Anything that can be compared using equality (==) can be used.
val things = "foo"

when (thingy) {
	"foo" -> println("Something")
	"bar" -> println("Something else")
	else -> println("And now for something completely different")
}
  • However, you cannot mix types, unless *== happens to work to compare them.
  • This, for example, fails with a compiler error, pointing out that Int and String are incompatible types:
val things = "foo"

when(things) {
	"foo" -> println("Something.")
	2 -> println("Something else.")
	else -> println("And now for something completely different")
}

Using when instead of else if

The when syntax from the preceding section is fairly similar to switch and case. However, when has many more options.

  1. One option is to skip the parameter to the when.
  • In that case, each branch has its own Boolean expression, and the first that evaluates to true is used.
  • This results in a more direct analogue to if else/ if else.
val i = 3

when {
	i > 10 -> println("Something")
	i > 2 -> println("Something else")
	else -> println("And now for something completely different")
}

Consolidating Multiple Branches

  • If you have a few values that all should route to the same branch, you can use a comma-delimited list instead of a single value for the branch comparison.
    • Kotlin will compare each of the comma-delimited values and if any of them match, that branch is used.
  • For numbers, you can use .. syntax and in to set up a "range" and test against it.
val thingy = "foo"

when(thingy) {
"foo", "goo" -> println("Something")
"bar", "baz", "frobozz" -> println("Something else")
else -> println("And now for something completely different")
}
val i = 3

when(i) {
in 3..10 -> println("Something")
in 1..2 -> println("Something else")
else -> println("And now for something completely different")
}

Expressions As Branch Conditions

  • The value for comparison does not need to be constant - any expression will work.
  • Here, the second branch compares thingy to otherThingy.toLowerCase() - in this case, they are equal, and so that branch is used.
val thingy = "bar"
val otherThingy = "BAR"

when(thingy) {
	"foo", "goo" -> println("Something")
	otherThingy.toLowerCase() -> println("Something else")
	else -> println("And now for something completely different")
}

While

Just as if is fairly common in programming languages, so is while or some other loop that is based on evaluating a condition.

Java
int i = 0

while(i < 10) {
i++;
}
JavaScript
var i = 0;
while(i < 10) {
i++;
}
Ruby
i = 0

while i < 10
i += 1
end
Kotlin
var i = 0

while(i < 10) {
i++
println(i)
}
  • However, while is not common in Kotlin as it is in other languages.
  • More often we use operations on collection (e.g, forEach()) rather than while.
  • However, it exists, should you find the need for it.

when Expressions

  • when can also be used as an expression:
val i = 3

val message = when(i) {
in 3..10 -> "Something"
in 1..2 -> "Something else"
else -> "And now for something completely different"
}

println(message) // Prints "Something".
  • Technically, the branches of the if or when do not have to evaluate to the same type.
val i = 3

val message = when(i) {
in 3..10 -> "Soemthing"
in 1..2 -> 5
else -> "And now for something completely different"
}

println(message) // Prints "Something"
  • However, you will get some compiler warnings:
     

enter image description here

  • Here, the compiler is telling you that since the branches evaluated to different types, the implied type of message is Any.
  • Any in Kotlin is roughly analogous to Object in Java - it is the root type of the class hierarchy.
    • Every class in Kotlin eventually extends from Any.
    • Any is the common ancestor class of Int and String, which is why the compiler chose that as the type for message.
  • The warning is there to hint to you that perhaps what you wrote is not what you really have in mind.

Else Required

  • Normally, if and when do not have to be exhaustive.
    • Exhaustive means that all possibilities are covered by some branch.

Examples for exhaustive:

if(i > 10) {
	// Do something.
}
else {
	// Do something else.
}

Examples for not exhaustive:

if(i > 10) {
	// Do something.
}
val i = 3

when  {
	i > 10 -> println("Something")
	i > 2 -> println("Something else")
}
  • In these cases, there are values for i for which none of the branches is valid.
     
  • For standalone if and when statements, this is fine.
  • However, if you are going to use if and when as expressions, they must be exhaustive.
     
  • If you try a non-exhaustive if or when for an expression, such as:
val i = 3

val message = when(i) {
	in 3..10 -> "Something"
	in 1..2 -> 5
}

println(message)

... you will get a compilation error.
 

enter image description here

Bustin' Out

Sometimes, while you in a loop, you will want to change the normal flow of the loop.

For example, you are in a for loop, and after the 5th item, you wish to exit the loop, perhaps in response to some signal (e.g., a cancellation flag was set).

  • You can always return to exit the entire function that you are in.
  • Beyond that, though, there are two loop control statements that you can use:
    • break.
    • continue.
  • These work much like their counterparts in Java and other programming languages.

break
  • Abandon the loop.
var i = 0
while(i < 10) {
	i++
	if(i == 5) break
	println(i)
}
  • Once i is equal to 5, we break out of the loop.
  • Since we are doing that before the println() call, we do not print 5 to the output.
1
2
3
4

continue
  • Skip the rest of this pass through the loop, and move along to the next pass through the loop.
var i = 0

while(i < 10) {
	i++
	if(i == 5) continue
	println(i)
}
  • We are going through the loop all 10 times, unlike in the break clause.
  • However, we are skipping part of the loop via continue -specifically we are skipping over the println() call.
1
2
3
4
6
7
8
9
10