Klitos Kyriacou
05/17/2022, 10:17 AMString
has a companion object whose only purpose is to allow extension functions, but unfortunately I've seen people who are beginners in Kotlin writing code like val x = foo()?: String
- presumably thinking String
is the empty string, and not realising that it's the companion object. I can't think of any syntax that would allow us to mark such objects as not allowable to be used in this way.xxfast
05/20/2022, 1:43 PMoverride
keyword? Do we really need it?Jonathan Ellis
05/27/2022, 7:03 PMExerosis
05/30/2022, 3:35 AMDaniele Segato
06/02/2022, 1:54 AMIsaac Udy
06/03/2022, 12:27 PMinterface Input<T> { ... }
interface Output<T> { ... }
fun <In: Input<T>, T> registerForOutput(): Output<T> { ... }
Based on the type of In
, I want to be able to use registerForOutput
to create an Output
instance of the same generic type.
In this situation, I refer to T
as the "nested generic type of `In`" in the context of registerForOutput
. To re-word the initial sentence: I want registerForOutput
to return an Output
with the nested generic type of In
.
Consider the following code:
class ConcreteInput : Input<String> { ... }
val output = registerForOutput<ConcreteInput, String>()
The code above provides a developer experience that is not ideal. A developer, despite knowing that ConcreteInput
uses String
as the generic type for its implementation of Input
, still needs to explicitly define String
as a secondary generic type of the call to registerForOutput
.
This is only a minor inconvenience in the case that Input
has a single generic type, but in the case that Input
has two, three, or even more generic types, this becomes significantly less enjoyable to work with.
I believe that this could be improved by including an "inferred" keyword, which is usable within generic type definitions.
Consider the following code:
fun <In: Input<inferred T>> registerForOutput(): Output<T> { ... }
In the code above, we state that T
, the generic type of the generic In
(the "nested generic" of In
) should be inferred by the compiler, meaning that it would be possible to write the following code, where the type out output
should be `Output<String>`:
val output = registerForOutput<ConcreteInput>()
The following code should infer that the T
of registerForOutput
is Int
, and the type of output
should be `Output<Int>`:
val output = registerForOutput<Input<Int>>()
The following code should infer that the T
of registerForOutput
is Nothing
, and the type of output
should be `Output<Nothing>`:
val output = registerForOutput<Input<*>>()
Ideally, the inferred
keyword that I am suggesting should be compatible with reified
, so that it's possible to write the following:
inline fun <In: Input<inferred reified T> registerForOutput(): Output<T> {
println(T::class.java.simpleName)
...
}
I am interested to hear feedback on whether or not this makes sense (or is possible) as a language feature!Mikhail
06/15/2022, 11:30 AMDavio
06/27/2022, 8:37 AMtoDoubleOrNull()
(similar functions exist for other numeric types). This extension function is defined on String
instead of String?
Would it make sense to define this function on String?
instead so a null-valued String just returns null?
I noticed that toBoolean()
is defined on String?
as well.Eric Ou
06/29/2022, 9:06 AMinline fun <T> T?.println(): T? {
println(this)
return this
}
so I dont have to move my caret around when trying to debuglouiscad
06/30/2022, 11:39 PMprivate val useMe
that you access in public fun callMe(…)
, if you want to make callMe
inline
, you are forced to change useMe
visibility to internal
and add the @PublishedApi
, which has the unintended effect of letting useMe
be accessed outside the file where it resides along with callMe
. I don't like to leave that door open as the intention is poorly communicated IMHO.
Here's my proposal: allow @PublishedApi
to target private
symbols.
The API would still be published, and tools like kotlinx api validator would need to take it into account, but it'd avoid exposing something in a module where it's only intended to be used in a file. What do you think?Andy McGhie
07/04/2022, 7:45 AMResult
it's often useful to map an exception to another type of exception, has there any thought been given to adding something like mapFailure
to the Result
i.e.:
inline fun <R> Result<R>.mapFailure(transform: (exception: Throwable) -> Throwable): Result<R> {
return when {
isFailure -> Result.failure(transform(exceptionOrNull()!!))
else -> this
}
}
Usage:
Result
.failure<String>(NullPointerException())
.mapFailure {
MyDomainException()
}
elect
07/04/2022, 9:29 AMclass Entity(val fields: Fields = ..,
val inner: Inner = ..,
val owner: Owner? = null)
right now if I want to pass owner
, I have to use named parameters Entity(owner = owner)
, which is redundant if the variable naming matches, imhoEmil Kantis
07/04/2022, 6:35 PMcontext(MyContext)
fun sayHello(name: String) {
println("Hello $name")
}
fun main() {
with(context) {
listOf("a", "b").forEach(::sayHello)
}
}
Right now it gives an error because sayHello is a KFunction2<MyContext, String,Unit>
when a (TypeVariable(T)) -> Unit
was expected.Eric Ou
07/05/2022, 10:51 AMfun timesTwo(num: Double[(s: String)->s.toDouble(), (n: Number)->n.toDouble()]) = num * 2
Which can be separated into two methods by the compiler, and this would get rid of conversion methods, which would reduce redundancy?
Though admittedly the syntax I designed for it is pretty bad, but I trust you guys can do better than I can :D.Slackbot
07/08/2022, 9:21 AMMikhail
07/18/2022, 1:02 AMilya.gorbunov
07/22/2022, 6:00 PM..
operator and until
function have their upper bound excluded or included.
Now we present the proposal intended to improve this situation by introducing the new ..<
(rangeUntil) operator to Kotlin. Please use KEEP-314 for the discussion.Jonathan Ellis
07/26/2022, 4:14 PMimport kotlin.test.Test
class Undefined {
init {
println({ -> foo }.invoke())
}
val foo = 0
}
class Foo {
@Test
fun testUndefined() {
Undefined()
}
}
fabianhjr
07/30/2022, 1:24 AM// ^ Try different backends
// v And commenting out or not
// @JvmInline
value class NonEmptyString(val value: String) {
init {
require(value.isNotEmpty())
}
}
fun main() {
println(NonEmptyString("Hello"))
try {
println(NonEmptyString(""))
} catch(e: Throwable) {
println("Woops!")
}
}
Sam Stone
08/02/2022, 7:48 AMfun <T> ld(t: T, getMessage: (T) -> String) = Timber.d(getMessage(t))
and fun <T> T.ld() = this.also { Timber
.d(it) }
The issue is that the class is always the util class. Writing val
`ld = {(insert previous code)
}` works for the former wrapper, but not the latter. I use the latery for chaining.Sam
08/04/2022, 7:54 AMdata class A(val name: String)
fun <B> A.getProp(prop: A.() -> B) = prop(this)
fun A.getName() = getProp(::name) // I want this
fun A.getName2() = getProp(A::name) // But I have to do this instead
Eric Ou
08/04/2022, 11:08 AMoperator fun usedAs(): SomeType
When the code is compiled, this method is automatically called if it's used as a parameter in that type.
That might be a bit confusing, let me elaborate.
operator fun String.usedAs(): URL = URL(this)
And then the user can use String in place of URL in method call and constructors. Then the compiler can desugar it to the method call.
Though since now you can't really have two methods with the same name, I would make it something more like
@Converter(URL::class)
fun asURL(): URL = //...
Eric Ou
08/04/2022, 11:23 AM*
to call multiply
instead of times
, and operator fun times(other: A) = multiply(other)
is just more boilerplate. Something like
@Operator(TIMES)
fun multiply(other: A) {
//...
}
would be cool :D.mcpiroman
08/04/2022, 5:48 PM@Volatile
) so there could be a meta annotation `@External`that only enables that annotations to be used externally.Michael de Kaste
08/08/2022, 10:16 AMfun holeFiller(spaces: Int, totalSum: Int): List<List<Int>> = buildList {
fun fill(sumToGo: Int, list: List<Int> = emptyList()) {
when (list.size) {
spaces - 1 -> add(list + sumToGo)
else -> for (i in 0..sumToGo) {
fill(sumToGo - i, list + i)
}
}
}
fill(totalSum)
}
However, if I want to have this with a sequence, the function "fill" needs to be specified as
suspend fun SequenceScope<List<Int>>.fill
It would be nice if an inner function of a sequence implicitly works like thisAyfri
08/08/2022, 4:51 PMSam Stone
08/12/2022, 7:29 PMInt
or a Long
? Either that, or convert the parameters to the expected type every time.
A solution could be including the arithmetic operations in Number
, besides for the conversions.David Rodrigues
08/13/2022, 10:06 PMreturn
a certain value based on a condition, and I'd like to propose this feature:
return x if != null
// <and/or>
return x if user != null
Same for break
or continue
Other examples:
return x if >= 5
return x if is User
return x if x + 1 >= 5
And maybe:
x = 5 if x < 2
stantronic
09/06/2022, 11:49 AMEllen Spertus
09/16/2022, 3:22 AMconst
keyword necessary? I understand that const val
is for compile-time constants and leads to different (presumably better) code than val
, but why couldn't the compiler generate the better code if a [static] val
is assigned a compile-time constant?
In other words, why does the compiler generate different code for these two lines?
const val PI = 3.1415
val PI = 3.1415