Can kotlin number cast type automatically?

annoying thing in kotlin is when casting number in kotlin JVM

example

// I have this java method
public static void foo(double bar){}

// in java I can do this
foo(10);

// in kotlin I can do
foo(10.0)
// or
val i = 10
foo(i.toDouble())

// below will showing as error in IntelliJ
// The integer literal does not conform to the expected type Double :C
foo(10)

My question is can kotlin cast a number automatically?

var a:Byte = 1 // yes
val b:Int = 1 // yes
a = b // what about this?
val c:Double = 1 // nah
val d:BigInteger = b // b is an int 
// if compiler can compile above line into `BigInteger.valueOf(b)` it's easy to use now
val d:BigDecimal = 1 
// new BigDecimal(d)  ?
val e:Double = a // if this can cast to double by compiler I'll very happy with it

fun foo(a:Double,b:BigDecimal){}
foo(1,2) // this will make everythings easier

// but if i add this
fun foo(a:Double,b:Int){}
foo(1,2) // should error due can't infer type

// but method like this should not use smart cast
operator fun Int.plus(bar:BigInteger){}

It was a deliberate choice by the language designer not make that happen. Whereas it might be convenient in some circumstances it’s often a cause of bugs.

1 Like

Can kotlin number cast type automatically? No, it is not possible. All numeric types are final (3 !is Long).

Can kotlin number convert type automatically? Sometimes

1 Like

I love the way the linked page says:

Absence of implicit conversions is rarely noticeable

That’s just not true in my experience!⠀Anything to do with endian conversion, RGB values, sound samples, packed data structures, keystrokes, manual character set conversion, or low-level InputStream/OutputStream/Reader/Writer usage is likely to involve some numeric conversions — often several in the same expression.⠀And it gets unwieldy and tedious really quickly…

I appreciate that Kotlin avoids some classes of bugs in this way.⠀And I like the principle of keeping the types clear.⠀But in practice it can be pretty painful — sometimes needlessly so.

For example, I can see no reason why they didn’t define bitwise operations on all the numeric types, instead of just Int and Long.⠀That alone would lessen some of the pain.

operations like this are generally restricted to a few specific libraries. Most of the time people will use a library that already handles that sort of stuff for them. I agree that in the case that you are the one maintaining such a library it’s anoying but I don’t think Kotlin should sacrifice safety just for a small number of projects if this issue doesn’t affect anyone else.

The reason for that is that the underlying bytecode instruction only work with Int and Long(JVM) which can lead to some unintuitive behaviour. I think there is an extension library adding those, not sure. In any case it’s not hard adding a utility file with a few extra extension functions to support this.

1 Like

The reason it can for constants is that it knows the result will be okay. In the general case it doesn’t know that b will fit into a byte. If you changed b to be 1000, that cannot be written to a byte so it forces you (as does Java) to be explicit about your intention.

As far as your first example consider this variation:

// I have this java method
public static void foo(double bar){ println("%f".format(bar)) }

// in java I can do this
foo(987654321012345678);

The result is 987654321012345730.000000 because there is a loss of precision in the conversion to double. Java thought that was OK, Kotlin designers require you to be explicit since the conversion can be lossy

1 Like

The forced number conversion safety was a conscious choice and it was actually a good choice. We have a lot of previous experience with C++/Python/Groovy and even Java, where implicit conversion brings many more problems than it solves.

In kotlin, it is possible to bypass conversion clutter, by defining local extensions that allow broader number usage. For example, you can write:

fun foo(number: Number) = foo(number.toDouble())

and use it inside your own module at your own risk.

1 Like

You can also use Arrow Meta with the Type Proofs plugin and define a @Coercion proof to allow for automatic conversion, but again, it is at your own risk.