Equal operator cannot be applied between primitive and boxed variable - kotlin

In Kotlin it is trivial to compare some Long value to 0 like this.
if (firstUnread == 0) {
return
}
But usually this error occurs. What is the best way to compare these values?
Operator '==' cannot be applied to 'Long' and 'Int'

0 is an Int in Kotlin.
try to replace it with 0L instead and it will work.

In Kotlin, there are no implicit widening conversions for numbers: https://kotlinlang.org/docs/reference/basic-types.html
In your code you are attempting to compare a Long (firstUnread) to an Int (0). Instead compare to 0L so you are comparing a Long to a Long.

You can easily add .toLong() method after any int number.
Just change your code to this:
if (firstUnread == 0.toLong()) {
return
}

Related

Input out of range for Int datatype, not passing a testcase

I am trying to solve the following question on LeetCode; Write a function that takes an unsigned integer and returns the number of '1' bits it has. Constraints: The input must be a binary string of length 32.
I have written the following code for that which works fine for inputs 00000000000000000000000000001011 and 00000000000000000000000010000000 (provided internally by the website) but give output 0 for input 11111111111111111111111111111101 and in my local compiler for the last input it says "out of range"
class Solution {
// you need treat n as an unsigned value
fun hammingWeight(n:Int):Int {
var num = n
var setCountBit = 0
while (num > 0) {
setCountBit++
num= num and num-1
}
return setCountBit
}
}
To correctly convert binary string to Int and avoid "out of range error", you need to do the following (I believe LeetCode does the same under the hood):
fun binaryStringToInt(s: String): Int = s.toUInt(radix = 2).toInt()
"11111111111111111111111111111101" is equivalent to 4294967293. This is greater than Int.MAX_VALUE, so it will be represented as negative number after .toInt() convertion (-3 in this case).
Actually, this problem could be solved with one-liner in Kotlin 1.4:
fun hammingWeight(n: Int): Int = n.countOneBits()
But LeetCode uses Kotlin 1.3.10, so you need to adjust your solution to handle negative Ints as well.
Please change the type of your input variable from Int to a type like Double .At the moment The given value is bigger than the maximum value that a type Int number can store.

Filtering out non null values from a collection in kotlin

Take a look at this kotlin one liner:
val nonNullArr : List<NonNullType> = nullArray.filter {it != null}
The compiler gives a type error at this line, saying that a list of nullables can't be assigned to a list of non-nulls. But the filter conditional makes sure that the list will only contain non null values. Is there something similar to !! operator that I can use in this situation to make this code compile?
It seems logical to assume that the compiler would take into account the predicate
it != null
and infer the type as
List<NonNullType>
but it does not.
There are 2 solutions:
val nonNullList: List<NonNullType> = nullableArray.filterNotNull()
or
val nonNullList: List<NonNullType> = nullableArray.mapNotNull { it }
As far as I know, you cannot convert nullable types into nonNull types by just verifying that they are not null. To achieve what you want, you need to manually map nullable values to non-null type by simply creating NonNull type object. For this you can use map extension function.
val nullableArray: Array<String?> = arrayOf("abc", "xyz", null, "efg")
val nonNullList: List<String> = nullableArray.filter { it != null }.map {
it.toString()
}
Or you can use filterNotNull() method as #forpas suggested in comments
val nonNullList: List<String> = nullableArray.filterNotNull()
Hope it helps you!
You can't assign a nullable type to a non-nullable type of value.
The type-matching maybe works when you assign a value, not after filter operation called.
// the type-matching works before `.filter` is called
val nonNullArr : List<NonNullType> = nullArray//.filter {it != null}
instead, if you want to do this without an error or without concerning the type. Remove the type from the val, so it goes like this
val nonNullArr = nullArray.filter {it != null}
Hope it helps
try using listOfNotNull instead of listOf(), it is equivalent to list.filterNotNull()

How do I compare a Short with an Int in Kotlin?

I have a Short variable that I need to check the value of. But the compiler complains that Operator '==' cannot be applied to 'Short' and 'Int' when I do a simple equals check:
val myShort: Short = 4
if (myShort == 4) // <-- ERROR
println("all is well")
So what's the simplest, "cleanest" way to do this equals check?
Here are some things I tried.
The first one casts the 4 integer to a short (looks weird, invoking a function on a primitive number)
val myShort: Short = 4
if (myShort == 4.toShort())
println("all is well")
The next one casts the short to an int (shouldn't be necessary, now I have two ints when I shouldn't really need any)
val myShort: Short = 4
if (myShort.toInt() == 4)
println("all is well")
Basically, the 'cleanest' way to compare it with a small constant is myShort == 4.toShort().
But if you want to compare a Short with a wider-type variable, convert myShort instead to avoid the overflow: myShort.toInt() == someInt.
looks weird, invoking a function on a primitive number
But it does not actually call the functions, they are intrinsified and compiled to bytecode that operates the numbers in a way that is natural for JVM, for example, the bytecode for myShort == 4.toShort() is:
ILOAD 2 // loads myShort
ICONST_4 // pushes int constant 4
I2S // converts the int to short 4
IF_ICMPNE L3 // compares the two shorts
See also: another Q&A concerning numeric conversions.
You could also create an infix function instead of ==. I called it eq
infix fun Short.eq(i: Int): Boolean = this == i.toShort()
And you can use it like this
val myShort: Short = 4
if (myShort eq 4)
println("all is well")

Kotlin: Cannot apply two conditionals at once check with "return body" function style

I have a simply function check like this:
fun parseValidBluetoothBrickedId(controllerId: String?): Boolean{
if(controllerId != null){
if(controllerId.startsWith(BLUETOOTH_NAME_PREFIX) && controllerId.length > BLUETOOTH_NAME_PREFIX.length)
return true
}
return false
}
I want to convert it to simplier style:
fun parseValidBluetoothBrickedId(controllerId: String?) =
controllerId?.length > BLUETOOTH_NAME_PREFIX.length
&& controllerId?.startsWith(BLUETOOTH_NAME_PREFIX)
but IDE(Android Studio 3.0 Beta7) gives me an error, underlines the greater than('>') operator:
Operator calls corresponds to a dot-qualified call 'controllerId?.length.compareTo(BLUETOOTH_NAME_PREFIX.length) which is not allowed here
Also it underline as an error line controllerId?.startsWith(BLUETOOTH_NAME_PREFIX) and says:
Type mismatch. Required: Boolean, Found Boolean?
What is the problem, really? It is just a simply method, works well with the first block if-else style.
You can't call compareTo (use the < operator) on controllerId?.length, since its type is Int?, which means it might be null, in which case it can't be compared as a number.
Similarly, the controllerId?.startsWith(BLUETOOTH_NAME_PREFIX) call returns Boolean? (since it will return null if controllerId is null), which can't be passed to the the && operator, only a real Boolean can.
The solution here is to do the null check that you were doing in your original method, and get rid of the safe calls by relying on smart casts casting your controllerId to String:
fun parseValidBluetoothBrickedId(controllerId: String?): Boolean =
controllerId != null
&& controllerId.length > BLUETOOTH_NAME_PREFIX.length
&& controllerId.startsWith(BLUETOOTH_NAME_PREFIX)
When you do controllerId?.length, you are getting an Int?. You cannot compare Int with an Int?. That is the reason you get the first error.
You get the other error because controllerId?.startsWith(BLUETOOTH_NAME_PREFIX) returns Boolean?. You cannot use the && operator on a nullable parameter. It requires two parameters of type Boolean.
To solve the problems, you need to check controllerId != null first. This will smart cast controllerId to the non-nullable type String. Like this:
fun parseValidBluetoothBrickedId(controllerId: String?): Boolean =
controllerId != null
&& controllerId.startsWith(BLUETOOTH_NAME_PREFIX)
&& controllerId.length > BLUETOOTH_NAME_PREFIX.length
Your transformed function is missing the null check:
fun parseValidBluetoothBrickedId(controllerId: String?) =
controllerId != null && controllerId.length > "".length
&& controllerId.startsWith("")
As in your first example, the null check is necessary for the compiler to know, that controllerId is not null. After the check, the compiler uses "smart casting" and the calls are safe.
Therefore you do not have to use ?. notation after the check.

comparison between pointer and integer ('int *' and 'int')

I am confused as to why I get this warning:
I intiate matchObsFlag with:
int *matchObsFlag=0;
but when I run this line:
if (matchObsFlag == 1)
I get this warning. Any ideas?
You surely get a warning because you did not cast 1 as such (int*) 1 so you test an equality between different things : an address and an int.
So it is either if(matchObsFlag == (int*)1) or if(*matchObsFlag == 1) depending on what you wanna do.
int *matchObsFlag=0;
The type of matchObsFlag is int* while the constant literal is of type int. Comparison between the unrelated types is causing the warning.
matchObsFlag is a NULL pointer. matchObsFlag needs to point to a valid memory location if you wish to compare the value pointed by the pointer.
int number = 1;
matchObsFlag = &number;
Now, to compare the value, you need to dereference the pointer. So try -
if (*matchObsFlag == 1)
{
// ...
}