Kotlin: Variable 'result' must be initialized - kotlin

The compiler is showing error Kotlin: Variable result must be initialized.
Here is the code.
fun main(args: Array<String>) {
print("Enter two numbers: ")
// nextDouble() reads the next double from the keyboard
var first= readLine()!!.toDouble()
var second = readLine()!!.toInt()
print("Enter an choice(1-4)): ")
val operator = readLine()!!.toInt()
var result: Double
when (operator) {
1 -> result = first + second
2 -> result = first - second
3 -> result = first * second
4 -> result = first / second
else -> {
println("Error.")
}
}
println("The result is :- " +result)
}

The problem is that when you read the value of result here:
println("The result is :- " +result)
result might not be initialized, because here:
var result: Double
when (operator) {
1 -> result = first + second
2 -> result = first - second
3 -> result = first * second
4 -> result = first / second
else -> {
println("Error.")
}
You are NOT assigning a value to result in the else branch. You have several options, one could be to make result nullable. For instance:
var result = when (operator) {
1 -> first + second
2 -> first - second
3 -> first * second
4 -> first / second
else -> null
}
if (result != null) {
println("The result is :- " + result)
} else {
println("Error.")
}
Notice that if the operator is not (1-4) the value of result will be null. Also, in your code you're printing "Error" and then again you're attempting to print the result.
To add something more, you could make the thing a bit nicer if you defined your operator with the when statement as a method reference:
print("Enter an choice(1-4)): ")
val operatorCode = readLine()!!.toInt()
val operator: ((Int) -> Double)? = when (operatorCode) {
1 -> first::plus
2 -> first::minus
3 -> first::times
4 -> first::div
else -> null
}
if (operator != null) {
val result = operator.invoke(second)
println("The result is :- " + result)
} else {
println("Error.")
}

As jrtapsell points out the main issue is that you declare result to be a Double but you since you don't cover every possible value in the when statement, you are accessing an un-initialized variable.
Another option, if you really operators other than 1-4 want it to be an error condition and don't want result to end up with a valid Double is to use Optionals.
fun main(args: Array<String>) {
print("Enter two numbers: ")
// nextDouble() reads the next double from the keyboard
var first= readLine()!!.toDouble()
var second = readLine()!!.toInt()
print("Enter an choice(1-4)): ")
val operator = readLine()!!.toInt()
var result: Double? = null
when (operator) {
1 -> result = first + second
2 -> result = first - second
3 -> result = first * second
4 -> result = first / second
else -> {
println("Error.")
}
}
// only print the result if not null
result?.let {
println("The result is :- " +result)
}
}
In this case result will be null if the operator is not one of 1-4.

What is the error message trying to tell you
Variable 'result' must be initialized.
This means there are paths through your code where you access result before you have given it a value.
This is a problem because it means you have probably missed off handling a condition.
How do you get through your code without setting result
If the user inputs 5 result is not set
How to fix
Either set result in the else branch, or give it a default value in the declaration

Related

Kotlin when change value

can i use when in Kotlin to change the value of an existing variable?
i understand this one:
val num = 1
val result = when {
num > 0 -> "positive"
num < 0 -> "negative"
else -> "zero"
}
println(result)
should be "positive"
but i want this( psuedo )....
val num = 1
var result = "init string"
//bunch of code here
// later....
result = when{
num > 0 -> "positive"
num < 0 -> "negative"
else -> "zero"
}
it writes positive, but it says "Variable "result" initializer is redundant.
What im missing here?
Thx
The line
var result = "init string"
is redundant because you leave no possibility of that value not getting overridden in the when statement. "init string" cannot be printed at the end of the code, the variable will always have one of the three possible values defined in the when.
But you can directly initialize result with the when statement:
fun main() {
var num = 1
// directly assign the result of the when statment to the variable
var result = when {
num > 0 -> "positive"
num < 0 -> "negative"
else -> "zero"
}
println(result)
}
This prints
positive
thank you for the answer.
But i can say....
fun main() {
var num = 1
// directly assign the result of the when statment to the variable
var result = when {
num > 0 -> "positive"
num < 0 -> "negative"
else -> "zero"
}
println(result)
// and then later reassign....
num = 2
result = when{
num == 2 -> "two"
else -> "not two"
{
println(result)
// prints two
}
So i cant reassign an existing string with a when statement, that is not initialized with an another when statement?
I hope this is readable. :)
Thank you.
dagogi

Kotlin idomatic way to get columns of connect four game when hovering over it

I want to realize a game of four . The new chip will hover under the mouse cursor and accoring to its x-coordinates I want to calculate the column over which it hovers atm (and where it will be inserted after a click)
At the moment I do sth like this:
fun whichColumnIsChip(chip : Chip) : Int{
val x = chip.x/2
val columnWidth = Chip.radius*2 + distanceBetweenColumns
val rightColumnBorder = IntArray(gamefield.columns.size){ i -> marginLeft+(i+1) * (Chip.radius*2 + distanceBetweenColumns) }
when {
x.betweenInclusive(0.0, rightColumnBorder[0].toDouble()) -> return 0
x.betweenInclusive(rightColumnBorder[0].toDouble(), rightColumnBorder[1].toDouble()) -> return 1
x.betweenInclusive(rightColumnBorder[1].toDouble(), rightColumnBorder[2].toDouble()) -> return 2
x.betweenInclusive(rightColumnBorder[2].toDouble(), rightColumnBorder[3].toDouble()) -> return 3
x.betweenInclusive(rightColumnBorder[3].toDouble(), rightColumnBorder[4].toDouble()) -> return 4
x.betweenInclusive(rightColumnBorder[4].toDouble(), rightColumnBorder[5].toDouble()) -> return 5
x.betweenInclusive(rightColumnBorder[5].toDouble(), rightColumnBorder[6].toDouble()) -> return 6
else -> return -10
}
}
So if my cursor hovers over in between the x-coordinates of the 3rd column I just want to return 3
The code above works as intended, but I am sure there is a much more idomatic and shorter way
Few improvements could be done
1) Since Kotlin's when is not only a statement but an expression as well, you can reduce this
when {
condition1 -> return 1
...
conditionN -> return N
}
to
return when {
condition1 -> 1
...
conditionN -> N
}
2) You can reduce copypaste by declaring a function that performs a check on given array and some index. In following example the function is declared as local in order to capture local variables x and rightColumnBorder, but it could be declared as regular or extension, it's up to you.
fun option1(): Int {
//...
val test = fun (i: Int) = x.betweenInclusive(
if (i > 0) rightColumnBorder[i - 1].toDouble() else 0.0,
rightColumnBorder[i].toDouble())
return when {
test(0) -> 0
test(1) -> 1
test(2) -> 2
test(3) -> 3
test(4) -> 4
test(5) -> 5
test(6) -> 6
else -> -10
}
}
However, in your particular case you can notice that returned result is determined by the given array index, so the whole when statement could be replaced with a loop:
fun option2(): Int {
//...
rightColumnBorder.forEachIndexed { idx, value ->
val from = if (idx > 0) rightColumnBorder[idx - 1].toDouble() else 0.0
if (x.betweenInclusive(from, value.toDouble())) {
return idx
}
}
return -10
}
OR
fun option3(): Int {
//...
val test = fun (i: Int) = x.betweenInclusive(
if (i > 0) rightColumnBorder[i - 1].toDouble() else 0.0,
rightColumnBorder[i].toDouble())
rightColumnBorder.forEachIndexed { i, _ -> if (test(i)) return i }
return -10
}

Kotlin when expression issue for calculating (calculator) new to kotlin

//Error due to receive type mismatch but it the logic seems ok to me
fun main(args : Array<String>){
println("Enter a number")
var a = readLine()
println("Choose your operator")
val operator = readLine()
println("Enter a second number")
var b = readLine()
var result = when (operator) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
"/" -> a / b
else -> "invalid operator or number"
}
println("Results = $result")
}
In this case, a and b are type String. This means they don't have the -, /, or * operators. I'm going to guess you probably want them to be Ints so you can perform mathematical operations with them.
To do that, we can convert them to Int after we read them:
println("Enter a number")
var a: Int = readLine()?.toInt() ?: throw IllegalArgumentException("Must be an Int")
println("Enter a second number")
var b: Int = readLine().toInt() ?: throw IllegalArgumentException("Must be an Int")
I've explicitly typed a and b as Ints in this example, so we can see how it works. What this new code says is "read a line of input and try to turn it into an Int, if that doesn't work, throw an IllegalArgumentException. You could rewrite this to keep trying, but we're going to leave that bit up to you.
One more thing I would fix is that result is type Any because it can be either an Int (if we know about the operator) or a String (if we don't). I would change it so the invalid operator also throws an exception.
And again, I've typed this explicitly as Int:
var result: Int = when (operator) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
"/" -> a / b
else -> throw IllegalArgumentException("Invalid operator")
}
The problem is that you have input value as string, you have to convert them to int.
Here my code:
fun main(){
println("Enter a number")
val a = readLine()?.toInt()
println("Choose your operator")
val operator = readLine()
println("Enter a second number")
val b = readLine()?.toInt()
if( a != null && b != null) {
val result = when (operator) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
"/" -> a / b
else -> "invalid operator or number"
}
println("Results = $result")
}
}

What is the function of the [0] in the reader.next()[0] line of the below code

import java.util.*
fun main(args: Array<String>) {
val reader = Scanner(System.`in`)
print("Enter two numbers: ")
// nextDouble() reads the next double from the keyboard
val first = reader.nextDouble()
val second = reader.nextDouble()
print("Enter an operator (+, -, *, /): ")
val operator = reader.next()[0]
val result: Double
when (operator) {
'+' -> result = first + second
'-' -> result = first - second
'*' -> result = first * second
'/' -> result = first / second
// operator doesn't match any case constant (+, -, *, /)
else -> {
System.out.printf("Error! operator is not correct")
return
}
}
System.out.printf("%.1f %c %.1f = %.1f", first, operator, second, result)
}
next() returns a String, so the [] operator is translated to the get method on String. With a 0 index, this call returns the first character of the String.
If reader.next() returns an array then operator will have the value of the first element of the returned array.

How to implement switch-case statement in Kotlin

How to implement equivalent of following Java switch statement code in Kotlin?
switch (5) {
case 1:
// Do code
break;
case 2:
// Do code
break;
case 3:
// Do code
break;
}
You could do like this:
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // Note the block
print("x is neither 1 nor 2")
}
}
extracted from official help
switch in Java is effectively when in Kotlin. The syntax, however, is different.
when(field){
condition -> println("Single call");
conditionalCall(field) -> {
print("Blocks");
println(" take multiple lines");
}
else -> {
println("default");
}
}
Here's an example of different uses:
// This is used in the example; this could obviously be any enum.
enum class SomeEnum{
A, B, C
}
fun something(x: String, y: Int, z: SomeEnum) : Int{
when(x){
"something" -> {
println("You get the idea")
}
else -> {
println("`else` in Kotlin`when` blocks are `default` in Java `switch` blocks")
}
}
when(y){
1 -> println("This works with pretty much anything too")
2 -> println("When blocks don't technically need the variable either.")
}
when {
x.equals("something", true) -> println("These can also be used as shorter if-statements")
x.equals("else", true) -> println("These call `equals` by default")
}
println("And, like with other blocks, you can add `return` in front to make it return values when conditions are met. ")
return when(z){
SomeEnum.A -> 0
SomeEnum.B -> 1
SomeEnum.C -> 2
}
}
Most of these compile to switch, except when { ... }, which compiles to a series of if-statements.
But for most uses, if you use when(field), it compiles to a switch(field).
However, I do want to point out that switch(5) with a bunch of branches is just a waste of time. 5 is always 5. If you use switch, or if-statements, or any other logical operator for that matter, you should use a variable. I'm not sure if the code is just a random example or if that's actual code. I'm pointing this out in case it's the latter.
The switch case is very flexible in kotlin
when(x){
2 -> println("This is 2")
3,4,5,6,7,8 -> println("When x is any number from 3,4,5,6,7,8")
in 9..15 -> println("When x is something from 9 to 15")
//if you want to perform some action
in 20..25 -> {
val action = "Perform some action"
println(action)
}
else -> println("When x does not belong to any of the above case")
}
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 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 satisfied 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.)
From https://kotlinlang.org/docs/reference/control-flow.html#when-expression
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.
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 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.
import java.util.*
fun main(args: Array<String>){
println("Hello World");
println("Calculator App");
val scan=Scanner(System.`in`);
println("""
please choose Your Selection to perform
press 1 for addition
press 2 for substraction
press 3 for multipication
press 4 for divider
press 5 for divisible
""");
val opt:Int=scan.nextInt();
println("Enter first Value");
val v1=scan.nextInt();
println("Enter Second Value");
val v2=scan.nextInt();
when(opt){
1->{
println(sum(v1,v2));
}
2->{
println(sub(v1,v2));
}
3->{
println(mul(v1,v2));
}
4->{
println(quotient(v1,v2));
}
5->{
println(reminder(v1,v2));
}
else->{
println("Wrong Input");
}
}
}
fun sum(n1:Int,n2:Int):Int{
return n1+n2;
}
fun sub(n1:Int, n2:Int):Int{
return n1-n2;
}
fun mul(n1:Int ,n2:Int):Int{
return n1*n2;
}
fun quotient(n1:Int, n2:Int):Int{
return n1/n2;
}
fun reminder(n1:Int, n2:Int):Int{
return n1%n2;
}
Just use the when keyword. If you want to make a loop, you can do like this:
var option = ""
var num = ""
while(option != "3") {
println("Choose one of the options below:\n" +
"1 - Hello World\n" +
"2 - Your number\n" +
"3 - Exit")
option = readLine().toString()
// equivalent to switch case in Java //
when (option) {
"1" -> {
println("Hello World!\n")
}
"2" -> {
println("Enter a number: ")
num = readLine().toString()
println("Your number is: " + num + "\n")
}
"3" -> {
println("\nClosing program...")
}
else -> {
println("\nInvalid option!\n")
}
}
}
val operator = '+'
val a = 6
val b = 8
val res = when (operator) {
'+' -> a + b
'-' -> a - b
'*' -> a * b
'/' -> a / b
else -> 0
}
println(res);
We use the following code for common conditions
val operator = '+'
val a = 6
val b = 8
val res = when (operator) {
'+',
'-' -> a - b
'*',
'/' -> a / b
else -> 0
}
println(res);
In kotlin, their is no switch-case statement. But we have when expression similar to switch. Just like if-else or switch, first all conditions are checked, if none matches then else code evaluated.
when (n) {
1 -> {
print("First")
// run your code
}
2 -> print("Second")
3, 4 -> print("Third or Forth") // check multiple conditions for same code
in 1..100 -> print("Number is in the range")
else -> {
print("Undefined")
}
}
There is no need of any break as of switch case.
Here is an example to know Using “when” with arbitrary objects,
VehicleParts is a enum class with four types.
mix is a method which accepts two types of VehicleParts class.
setOf(p1, p2) - Expression can yield any object
setOf is a kotlin standard library function that creates Set containing the objects.
A set is a collection for which the order of items does not matter.
Kotlin is allowed to combine different types to get mutiple values.
When I pass VehicleParts.TWO and VehicleParts.WHEEL, I get "Bicycle".
When I pass VehicleParts.FOUR and VehicleParts.WHEEL, I get "Car".
Sample Code,
enum class VehicleParts {
TWO, WHEEL, FOUR, MULTI
}
fun mix(p1: VehicleParts, p2: VehicleParts) =
when (setOf(p1, p2)) {
setOf(VehicleParts.TWO, VehicleParts.WHEEL) -> "Bicycle"
setOf(VehicleParts.FOUR, VehicleParts.WHEEL) -> "Car"
setOf(VehicleParts.MULTI, VehicleParts.WHEEL) -> "Train"
else -> throw Exception("Dirty Parts")
}
println(mix(VehicleParts.TWO,VehicleParts.WHEEL))
If You want to print or open multiple Activities using switch case (When) in Kotlin then use this code.. Thank you..
var dataMap: Map<String?, String?> = HashMap()
var noteType: String? = ""
when (noteType) {
"BIGTEXT" -> NEW_PAGE(dataMap)
"NORMAL" -> NORMAL_PAGE(dataMap)
"ABOUT"->ABOUT_PAGE((dataMap))
}