1

This is my first day of learning Kotlin and I have code like this:

val tagInfo : UHFTAGInfo? = rfid.readTagFromBuffer()
if (tagInfo != null) {
    val msg = hnd.obtainMessage()
    msg.obj = tagInfo
    hnd.sendMessage(msg)
}

Can I reduce it by one line by obtaining a value from rfid.readTagFromBuffer() and checking it for null?

In modern C# we can do it like this:

if (rfid.readTagFromBuffer() is UHFTagInfo tagInfo){
    val msg = hnd.obtainMessage()
    msg.obj = tagInfo
    hnd.sendMessage(msg)
}

I have tried to find answer here:

https://kotlinlang.org/docs/typecasts.html

but no success. So I assume Kotlin does not offer such feature, but maybe there is something similar that can reduce these two lines to one?

Kamil
  • 13,363
  • 24
  • 88
  • 183
  • Just to note: You've defined `tagInfo` to be `UHFTAGInfo`, which is a _non-nullable_ type. If `rfid.readTagFromBuffer()` can return null, then the type of the variable should be `UHFTAGInfo?`. – Slaw Sep 25 '22 at 20:04
  • @Slaw Yes, that method returns null when there is no more data to read. Actually I have `val` there, but I changed it to `UHFTagInfo` make more similar to C# code I wrote. Anyway, thank you for pointing it out, I have to remember that without `?` objects are non-nullable. – Kamil Sep 25 '22 at 20:25
  • @Slaw If I have Java function `public synchronized UHFTAGInfo readTagFromBuffer()` and `val` or `var` - Kotlin inferred type will be `UHFTAGInfo?`, right? – Kamil Sep 25 '22 at 20:32
  • 1
    Unless your Java method has a ["nullability annotation"](https://kotlinlang.org/docs/java-interop.html#nullability-annotations) on its return type, then the _inferred_ type will be a ["platform type"](https://kotlinlang.org/docs/java-interop.html#null-safety-and-platform-types) (`UHFTAGInfo!`). That makes it work the same as in Java, where any object reference may or may not be null. You can choose to make the type explicitly nullable (`UHFTTAGInfo?`) or non-nullable (`UHFTTAGInfo`), where in the latter case a non-null assertion will be inserted by the compiler (similar to `!!` I assume). – Slaw Sep 25 '22 at 20:45

1 Answers1

3

We can use one of scope functions e.g. let() with safe call operator:

rfid.readTagFromBuffer()?.let { tagInfo ->
    val msg = hnd.obtainMessage()
    msg.obj = tagInfo
    hnd.sendMessage(msg)
}

?. makes sure that let() is invoked only if the result of readTagFromBuffer() is not null and let() invokes the provided lambda passing tag info as the first argument.

Kotlin was designed in a way that instead of introducing a lot of different features and syntaxes to solve very specific problems, we have basic and powerful building blocks like scope functions and we can use them to satisfy different kinds of needs. No need to introduce a very specific syntax for this case.

broot
  • 21,588
  • 3
  • 30
  • 35
  • So lambda is the answer. Thanks. I think guys who work on C# introduced such syntax to let user choose between procedural and functional approach. – Kamil Sep 25 '22 at 18:46
  • 1
    @Kamil Yes, Kotlin uses lambdas and higher-order functions very extensively. BTW, please be aware `let()` is entirely inlined, so the above code produces identical or very similar bytecode to your first code sample. – broot Sep 25 '22 at 19:01