Overload resolution ambiguity on Int.toBigDecimal in Kotlin - kotlin

I want to convert integers to bigDecimals. However, it seems that IntelliJ'Idea sees twice the definition for the toBigDecimal().
when trying on the REPL I get this error:
12.toBigDecimal()
error: overload resolution ambiguity:
#SinceKotlin #InlineOnly public inline fun Int.toBigDecimal(): BigDecimal defined in kotlin
#SinceKotlin #InlineOnly public inline fun Int.toBigDecimal(): BigDecimal defined in kotlin
Meanwhile it is fine using Strings:
"12".toBigDecimal()
res1: java.math.BigDecimal = 12
I am using Kotlin version 1.3.61 (JRE 1.8.0_232-b09)
I am very confused and I don't know waht to look after. any pointers?

I have just experienced the same issue and managed to solve it.
Just right click on the error and select ignore in compile and it will compile and run fine.

Related

Kotlin Function Generics - Upper Bound Not Working

I faced some issue regarding usage of Kotlin generics in functions
fun <T : CharSequence> doSomething(): T {
return String() as T
}
class Something(intValue: Int)
Something(doSomething()) // Doesn't show any compile error
Now when it is executed it throws error
java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Number
Wanted to know why Kotlin compiler is not throwing error for incompatible typecasting
I think what you are seeing is the major compiler bug KT-47664. Though in the bug report they used a much more complex example to demonstrate the issue, the cause of the bug is the same, that being the compiler has inferred an empty intersection type (the intersection of CharSequence and Int is empty) as the type parameter.
The algorithm apparently treats an empty intersection type the same as any other type, doesn't think anything special of it, and so type inference succeeds.
This bug has been fixed by KT-51221 Deprecate inferring type variables into an empty intersection type. From what I understand from reading the reports, there will now be a warning if an empty intersection type is inferred. However, the fix is only included in Kotlin 1.7.20+, which at the time of writing, is not released yet :(

Kotlin compiler shows compilation error and suggests to "change type from 'T' to 'T"' while there is only one T in the context

I tried to implement some type classes from Haskell but confronted the issue that is probably a bug in the Kotlin compiler.
interface Semigroup<Instance> {
infix fun Instance.assocOp(oother: Instance): Instance
}
inline fun <reified T: Semigroup<T>> Iterable<T>.concat() = this.reduce<T, T> { acc: T, t: T -> acc.assocOp(t) }
The error message is "Expected parameter of type T".
IDEA suggests to "Change type from 'T' to 'T'" (does nothing).
I expect acc to belong to the type T mentioned in generics. But because of some reason compiler tries to find some other type T. I tried to
specify the type explicitly/implicitly
build ignoring IDEA message
change used version of Kotlin compiler (I have tried 1.4.20, 1.4.10, 1.3.72).
Nothing worked.
I suppose that writing the function without reduce (manually) may help to deal with it. Also, writing java code doing the same may help to mitigate the problem. But these solutions are only workarounds for the problem. Is the issue my fault or the compiler bug?
The compiler error clearly is not helpful here. However, it is correct that the code should not compile IMO.
You're defining the method assocOp as a member extension function. The extension applies to any type T, but it's a member of the interface Semigroup<T>.
To call that extension, you need both a receiver or type T and a receiver of type Semigroup<T> (acting as a context).
In your case, the type T both plays the role of the generic type parameter and of the Semigroup<T>, but you still need to have 2 "receivers" for your extension, even if both are the same instance.
Maybe try this:
inline fun <reified T : Semigroup<T>> Iterable<T>.concat(): T =
reduce<T, T> { t1: T, t2: T -> with(t1) { t1.assocOp(t2) } }
The with(t1) { ... } provides a context of type Semigroup<T>, while the t1 used in t1.assocOp(t2) acts as the T receiver.

Kotlin REPL Arithmetic

I just got started with a book on Kotlin and guess what? yes I can't figure out anything. Here is the thing
just by using REPL you can run part of your code and see if it runs without the need of creating a new file but I got a beautiful error message when I try to do min (43, -33), or any min(), max() and so on.
here is the error examples:
max(22, 33)
error: unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
min(93, -99)
error: unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public fun <T : Comparable<TypeVariable(T)>> Array<out TypeVariable(T)>.min(): TypeVariable(T)? defined in kotlin.collections
public fun Array.min(): Double? defined in kotlin.collections
Thanks to all and appreciate any help!!!
The min() and max() funtions are not part of the core language, the are defined in the standard library in the kotlin.math package. You need to import the package, than you can use these methods:
import kotlin.math.*
min(22, 33)

Kotlin thinks that two methods have the same JVM signature, but the actually don't

I came from the C# background and I know how to implement this in C#, but I'm struggling with Kotlin.
I've got 2 extension functions:
fun <T> Foo<T>.myFunction(func: () -> Unit): Foo<T>
and
fun <T> Foo<T>.myFunction(func: () -> Foo<T>): Foo<T>
Clearly, the return type of func is different in both functions. The first function executes it and returns this, the second executes func and returns the result of func.
But it gives me an error:
"Platform declaration clash: The following declarations have the same JVM signature".
How to implement this correctly in Kotlin?
Your functions have a conflicting signature within the JVM due to type erasure (the internal Function0<T> class being used to represent the function parameters); and you can fix this by giving each of them a JVM specific name. From Kotlin you would still access them by the original name, but from Java or internally another name is actually used. Simply use the #JvmName annotation on the alternative versions:
fun <T> Foo<T>.myFunction(func: () -> Unit): Foo<T>
#JvmName("myfunctionWithFoo")
fun <T> Foo<T>.myFunction(func: () -> Foo<T>): Foo<T>
On the JVM, we have to contend with type erasure. Meaning essentially that the types (T in this case) are thrown away in the compiled bytecode and that required checks are only done at compile time. Given that, you have to look at your function declaration with that in mind.
Kotlin will define your function argument as a Function0 in both cases. Because the types are erased, () -> Unit and () -> Foo<T> both look the same in the bytecode. We can prove this out by decompiling the code you've provided (I renamed one of these myFunction2 to get this to work):
public final class com/ginsberg/KotlinStuffKt {
public final static myFunction(Lcom/ginsberg/Foo;Lkotlin/jvm/functions/Function0;)Lcom/ginsberg/Foo;
public final static myFunction2(Lcom/ginsberg/Foo;Lkotlin/jvm/functions/Function0;)Lcom/ginsberg/Foo;
}
This is what the Kotlin compiler is generating (it does more, but I have removed the non-essential parts from this example). As you can see, our types are gone thanks to type erasure. And if we undo my change (myFunction2 becomes myFunction), there's no way at all to tell these apart. This is what the compiler is complaining about - if you erase the types the JVM can't tell these functions apart.

Kotlin: Why can't I use one of my functions?

I am trying to use one of my defined functions that accepts a string yet the software won't compile.
fun passes(address: String) = Collections.frequency(addresses, address) <= CONNECTIONS_PER_IP
fun passes(remoteAddress: InetSocketAddress) = passes(remoteAddress.hostName)
I can't even call the string function using a custom string, for example passes("127.0.0.1").
None of the following functions can eb called with the arguments supplied.
passes(String) defined in abendigo.Firewall
passes(InetSocketAddress) defined in abendigo.Firewall
I presume you're using java.lang.String instead of kotlin.String in the Kotlin source code. Please use only kotlin.String instead, this is the type that string literals in Kotlin have (but in the bytecode it's still transformed to java.lang.String).
The issue was an import of java.lang.String. For some reason IntelliJ imported it.