Vampire
03/12/2024, 3:09 PM@JvmName to be able to produce valid bytecode?Youssef Shoaib [MOD]
03/12/2024, 3:24 PMfun foo(bar: Int)
fun foo(baz: Int, unit: Unit = Unit)hfhbd
03/12/2024, 3:25 PMephemient
03/12/2024, 3:36 PM@JvmName and sufficient @Suppress you can
@JvmName("fooX")
@Suppress("CONFLICTING_OVERLOADS")
fun foo(x: Int) { println("foo(x = $x)") }
@JvmName("fooY")
@Suppress("CONFLICTING_OVERLOADS")
fun foo(y: Int) { println("foo(y = $y)")}
foo(x = 1)
foo(y = 2)Vampire
03/12/2024, 4:18 PMVampire
03/12/2024, 4:28 PMvararg pleaseUseNamedArguments: Unit, ๐Landry Norris
03/12/2024, 8:15 PMephemient
03/12/2024, 11:14 PMephemient
03/12/2024, 11:15 PMdmitriy.novozhilov
03/13/2024, 10:34 AMVampire
03/13/2024, 12:18 PMJvmName.dmitriy.novozhilov
03/13/2024, 12:23 PMVampire
03/13/2024, 12:42 PMdmitriy.novozhilov
03/13/2024, 12:47 PMVampire
03/13/2024, 12:47 PMVampire
03/13/2024, 12:47 PMVampire
03/13/2024, 12:49 PMf(a = 2), where a is a parameter specified in the declaration of f. Such calls are treated the same way as normal calls, but the overload resolution sets are filtered to only contain callables which have matching formal parameter names for all named parameters from the call.
>
> Important: this filtering is done before we perform selection of the overload candidate set w.r.t. rules for the respective type of call.Vampire
03/13/2024, 12:50 PMdmitriy.novozhilov
03/13/2024, 12:53 PM// FILE: a.kt
package a
fun foo() {} // (1)
// FILE: b.kt
package b
fun foo() {} // (2)
// FILE: c.kt
import a.*
import b.*
fun test() {
foo() // ambiguity between (1) and (2)
}
But you can't declare two functions with same signature in one namespace (package/class), as it produce conflict of overloads
// FILE: a.kt
fun foo() {} // conflicting
fun foo() {} // overloadsVampire
03/13/2024, 12:57 PMVampire
03/13/2024, 12:57 PMdmitriy.novozhilov
03/13/2024, 12:59 PM@BinarySignatureName proposal will be implementedVampire
03/13/2024, 1:00 PMVampire
03/13/2024, 1:01 PMdmitriy.novozhilov
03/13/2024, 1:02 PMdynamic in js), but we are trying to minimize their number to keep the language unifieddmitriy.novozhilov
03/13/2024, 1:03 PMYoussef Shoaib [MOD]
03/13/2024, 1:05 PMfun main() {
println(foo(a = 0))
println(foo(b = 0))
// println(foo(0)) errors
}
fun foo(a: Int, unit: Unit1 = UnitImpl) = a
fun foo(b: Int, unit: Unit2 = UnitImpl) = b + 42
sealed interface Unit1
sealed interface Unit2
private object UnitImpl: Unit1, Unit2
(Using Unitx because naming is hard)
Note that UnitImpl is private so that it can never be specified, and hence one can't discriminate between the overloads except by using the names. You might choose to make it public so that one can avoid using named parameters and instead doing UnitImpl as Unit1Vampire
03/13/2024, 1:05 PMThis can be said about anything, actually
E.g. about ternary operatorNo, that's just a very missed feature you refuse to implement. ๐
Vampire
03/13/2024, 1:07 PMBtw, here's a perfectly legal way to do what you want in Kotlin while ensuring that no overload is preferred when no named parameter is usedHow is it, compared to your other proposal at the beginning of the thread? ๐
Youssef Shoaib [MOD]
03/13/2024, 1:09 PMfoo(0) to the unit-less overload, this one instead ensures that there's no possible disambiguation without simply specifying the parameter namesVampire
03/13/2024, 1:10 PMYoussef Shoaib [MOD]
03/13/2024, 1:12 PMUnitImpl implement them. I'm using one object because old Android habits. I think this solution is "good enough".Vampire
03/13/2024, 1:14 PMVampire
03/13/2024, 1:14 PMYoussef Shoaib [MOD]
03/13/2024, 1:17 PMUnit1 vs Unit2Vampire
03/13/2024, 2:11 PMephemient
03/13/2024, 2:29 PMsealed class Nothing1
sealed class Nothing2
fun foo(x: Int, unused: Nothing1? = null) {}
fun foo(y: Int, unused: Nothing2? = null) {}Youssef Shoaib [MOD]
03/13/2024, 2:30 PMobject Unit1 and object Unit2Vampire
03/13/2024, 2:35 PMNullPointerException at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerialInfoImplJvmIrGenerator.getImplClass(SerialInfoImplJvmIrGenerator.kt:57) >:-DYoussef Shoaib [MOD]
03/13/2024, 2:36 PMsealed btw, it was just meant to prevent someone from implementing it and thus choosing an overload in a convoluted wayVampire
03/13/2024, 2:36 PMVampire
03/13/2024, 4:08 PMopen it should not be necessary, should it?Vampire
03/13/2024, 6:01 PMfun foo(bar: Int, @Suppress("UNUSED_PARAMETER") overloadSelector: ByBar? = null) = ...
fun foo(baz: Int, @Suppress("UNUSED_PARAMETER") overloadSelector: ByBaz? = null) = ...
class ByBar private constructor()
class ByBaz private constructor()
Now I can from Kotlin consumer do
foo(bar = 1)
foo(baz = 2)
And for example from Groovy consumer
foo(1, null as ByBar)
foo(2, null as ByBaz)
or from Java consumer
foo(1, (ByBar) null)
foo(2, (ByBaz) null)