Null-save arithmetic operations (a /? b)


#1

From time to time I have to work with nullable numbers in Kotlin. Kotlin has a lot of instuments for working with nullable types, but I believe it lacks support of arithmetic operations on them.

For instance, consider the following snippet:

var a: Double? = 10.0
var b: Double? = 20.0
var c = if (a != null && b != null) a / b else null

Here we need to check both variables for null before applying division - too much code

The situation gets worse when operands are mutable fields

class Test {
    var a: Double? = null
    var b: Double? = null;
    var c: Double? = null;
}

class TestService() {
    fun calculateValues(test: Test) {
        val a = test.a
        val b = test.b
        if (a != null && b != null)
            test.c = a / b
    }
}

My suggestion is to add arithmetic operators, that can accept nullable arguments and return null if one of the arguments is null: something like that

var a: Double? = 10.0
var b: Double? = 20.0
var c = a /? b

and

class TestService() {
    fun calculateValues(test: Test) {
         test.c = test.a /? test.b
    }
}

#2

Defining whole new set of operators just to solve this narrow use case is a bit strange (I am totally opposed to that idea). If you really need it, I think you can create new class like that:

class SmartDouble(val a: Double?){
    operator fun div(b:Double?): Double?{
        return if (a != null && b != null){
             a / b
        } else{
            null
        }
    }
}

#3

There is no need to define additional classes.
Just define extension methods like this:

operator fun Double?.div(other: Double?) = if (this != null && other != null) this / other else null

#4

Also, if you need “invalid propagating” arithmetic, you can always use Double.NaN instead of nulls.


#5

I thought about that. But I am not sure it will work, since method signature looks the same as div already defined for Double. In that case extension method won’t work since implemented method always shadows extension.


#6

It works because objects of type Double? are not instances of Double, so it’s not even possible to call Double.div with Double?s.