Kotlin initializ val with conditions - kotlin

In c++ const can be defined by
void func(const int param) {
const int VALUE = param > 0 ? param : 0;
...
}
In Kotlin I am trying to use when:
fun func(param: Int) {
val VALUE = when(param)
when(param) {
param > 0 -> param // Error: expression `param > 0` is not Int
else -> 0
}
...
}
What is the kotlin way to say expression ? value0 : value1?

Kotlin if one line like this :
var yourVAr=if(condition)value1 else value2

Related

if else return in kotlin

Error :
Kotlin: Type mismatch: inferred type is String but Unit was expected
code :
fun main() {
val a = 2
var data: String = if (a != 2) {
return "Hello"
} else {
return "World"
}
}
Your code should be like this
var data: String = if (a != 2) {
"Hello"
} else {
"World"
}
By using return you are returning from the main function which has the return type set to "Unit". If you want to display the text, you should then call println(data).
Fun fact, when used like this you can even ignore the "{}" and make it one line like this :
var data: String = if (a != 2) "Hello" else "World"

How to create list/set of functions in Kotlin

I have this code in java
// set of functions to transform int to String
private static final Set<IntFunction<String>> RULE_SET = new LinkedHashSet<IntFunction<String>>() {{
add(i -> i % 2 == 0 ? "buzz" : "");
add(i -> i % 3 == 0 ? "fizz" : "");
add(i -> i % 4 == 0 ? "2gis" : "");
}};
//client code
private String transformNum(int num) {
final String transformed = RULE_SET.stream()
.map(rule -> rule.apply(num))
.collect(Collectors.joining());
return transformed.length() == 0 ? String.valueOf(num) : transformed;
}
and now I'm trying to transform it to Kotlin.
But I feel that there is much simpler and easier way to create collection of functions, could you please advise? There is what I have now. Works, but looks weird for me, like I'm using Java in Kotlin, but not Kotlin itself. :)
private val rules = setOf<IntFunction<String>>(
IntFunction { i: Int -> if (i % 2 == 0) "buzz" else "" },
IntFunction { i: Int -> if (i % 3 == 0) "fizz" else "" },
IntFunction { i: Int -> if (i % 4 == 0) "2gis" else "" }
)
private fun transformNum(num: Int): String {
val transformed = rules.joinToString("") { rule: IntFunction<String> ->
rule.apply(num)
}
return if (transformed.isEmpty()) num.toString() else transformed
}
maybe this?
val ss = setOf<(Int) -> String>(
{ i -> if (i%2 == 0) "apple" else ""},
{ i -> if (i%3 == 0) "banana" else ""},
{ i -> if (i%4 == 0) "cherry" else ""}
)
private fun transform(num: Int): String =
ss.joinToString(""){ it(num) }
.let {
if (it.isEmpty()) num.toString() else it
}
Maybe this?
private val rules = setOf(
{ i : Int -> if (i % 2 == 0) "buzz" else "" },
{ i : Int -> if (i % 3 == 0) "fizz" else "" },
{ i : Int -> if (i % 4 == 0) "2gis" else "" }
)
and
private fun transformNum(num: Int) = rules.joinToString("") {it(num)}.run {
if (isEmpty()) num.toString() else this
}

Any performance cost with using "when" instead of "if-else"?

While developing, I've found that using when looks nicer a lot of the times compared to if-else. So, I'm curious whether using when instead of the typical if-else in simple situations have a performance impact (even if it's small). An example is doing:
val someNumber = when (someObject) {
null -> 0
else -> someCalculation()
}
versus
val someNumber = if (someObject == null) {
0
} else {
someCalculation()
}
Is there a performance difference between the two?
tl;dr: No you should not expect when to slow anything down.
The compiler reuses if/else, switch and ternary operator constructs in order to express when statements. Take this example:
fun whenApplication(someObject: String?) = when (someObject) {
null -> 0
else -> 2
}
And its bytecode shown as Java code:
public static final int whenApplication(#Nullable String someObject) {
return someObject == null ? 0 : 2;
}
Slightly more complex when-tests are shown here:
fun whenApplication(someObject: Any?) = when (someObject) {
is Int -> 2
in 0..2 -> 4
else -> 5
}
And the corresponding bytecode as Java:
public static final int whenApplication(#Nullable Object someObject) {
int var10000;
if (someObject instanceof Integer) {
var10000 = 2;
} else {
byte var2 = 0;
var10000 = CollectionsKt.contains((Iterable)(new IntRange(var2, 2)), someObject) ? 4 : 5;
}
return var10000;
}

Kotlin equivalent for Optional::map in Java8

Do you know if there is a shortcut for:
if (x == null) null else f(x)
For Java Optional you can just do:
x.map(SomeClass::f)
Kotlin utilizes its own approach to the idea of Option, but there're map, filter, orElse equivalents:
val x: Int? = 7 // ofNullable()
val result = x
?.let(SomeClass.Companion::f) // map()
?.takeIf { it != 0 } // filter()
?: 42 // orElseGet()
I ended up writing a full comparison here:
You can use let in this case, like this:
fun f(x : Int) : Int{
return x+1
}
var x : Int? = 1
println(x?.let {f(it)} )
=> 2
x = null
println(x?.let {f(it)} )
=> null
and as #user2340612 mentioned, it is also the same to write:
println(x?.let(::f)
You can try with let (link to documentation):
x?.let(SomeClass::f)
Example
fun f(n: Int): Int {
return n+1
}
fun main(s: Array<String>) {
val n: Int? = null
val v: Int? = 3
println(n?.let(::f))
println(v?.let(::f))
}
This code prints:
null
4

kotlin division of nullable arguments

Suppose, I have a class of the following structure
class Test {
var a: Double? = null
var b: Double? = null;
var c: Double? = null;
}
a and b are set somewhere else, and c should be calculated as a / b or null if at least one of the arguments is null. Is there an easy way to achieve this in Kotlin?
I has to do it the following way now:
fun calculateValues() {
...
val a = test.a
val b = test.b
if (a != null && b != null)
test.c = a / b
...
}
class Test {
var a: Double? = null
var b: Double? = null
val c: Double? // It should be val as it is readonly
get() {
// This is need as a & b are mutable
val dividend = a
val divisor = b
if (dividend == null || divisor == null)
return null
return dividend / divisor
}
}
test.apply {
c = if (a==null || b==null) null else a/b
}
Of course that can be included as a getter of c (which in turn avoids storing c as a field):
class Test {
var a: Double? = null
var b: Double? = null
var c: Double? = null
get() = if (a==null || b==null) null else a/b
}
If Test is not a class of yours, you can always use an extension function:
fun Test.updateC() {
c = if (a==null || b==null) null else a/b
}
and that can then be called on a Test instance just like any other function of the Test class: test.updateC()
If you need to make sure about nullability at the time of computing a/b, you should use temporary variables as indicated in #Joshua answer below. Or also read the following Kotlin discussion: https://discuss.kotlinlang.org/t/kotlin-null-check-for-multiple-nullable-vars/1946/11 and ticket: https://youtrack.jetbrains.com/issue/KT-20294
I especially like the reusable solution with a function:
fun notNull(vararg args: Any?, action: () -> Unit) {
when {
args.filterNotNull().size == args.size -> action()
}
}
which can be used then as:
c = null
notNull(a, b) { c = a/b }
As the logic is outside of Test class I don't find the problem of checking nullability before making the operation. Anyway, if else is also an expressión in Kotlin so you could do the following:
val a = test.a
val b = test.b
t.c = if (a != null && b != null) a / b else null