Jaebaek Seo
04/16/2025, 8:56 PMDerek Peirce
04/27/2025, 6:02 AMCompletable.doOnEvent, which takes a lambda `(Throwable?) -> Unit`:
myCompletable.doOnEvent { doSomething() }
However, this started throwing exceptions. As it is a Java method, Kotlin automatically regarded it as Throwable! and therefore Throwable, and as soon as the lambda was called with a null value, it did a null check and threw a NPE, even though it was verifying a value that went completely unused.
As the only reason Kotlin automatically treats Throwable! as Throwable here is for convenience, could it recognize in this case that the parameter is entirely unused, and therefore not overeagerly perform a null check? The solution to avoid the exception is to specify { _: Throwable? -> doSomething() }, which I'd rather not need to specify, and I'd especially have preferred not to have to deal with the exception in the first place at all.Daniele Segato
05/22/2025, 3:36 PM? and !! will be used as well for error types, how are we going to differentiate between null and error in a function returning a nullable type?
fun foo() String? | SomeError
I was surprised this wasn’t addressed at all in the talk.
Are we supposed to either write functions with error union types OR functions returning nullable without error union types?
What about generics versions of this?
A null can be a valid successful responseYoussef Shoaib [MOD]
05/27/2025, 4:43 PMfun <T> add(first: T, second: T)
Nor this function:
context(t: T) fun <T> foo(list: MutableList<T>)Alejandro Serrano.Mena
06/06/2025, 9:46 AMmikhail.zarechenskiy
06/06/2025, 10:51 AMRoman Efremov
06/10/2025, 3:30 PMFaiz Ilham
06/10/2025, 5:17 PMRuckus
06/16/2025, 3:25 PMJP Sugarbroad
06/20/2025, 3:35 PMAlejandro Serrano.Mena
07/02/2025, 10:56 AMRoman Efremov
07/14/2025, 12:05 PMjoseph_ivie
07/31/2025, 2:17 PMtype.
// expect files only
expect type ViewNode
expect type TextInput: ViewNode
expect val TextInput.content: String
// actual files only
actual typealias ViewNode = HTMLElement // js
actual typealias ViewNode = View // android
actual typealias ViewNode = UIView // ios
actual typealias TextInput = HTMLInputElement // js
actual typealias TextInput = EditText // android
actual typealias TextInput = UITextField // ios
actual fun TextInput.content get() = this.value // js
actual fun TextInput.content get() = this.text // android
actual fun TextInput.content get() = this.text // ios
type would have no restrictions about what the actual is - it could be a class, interface, open class, or more.
Consequently, you wouldn't be able to use the type for anything other than an input, output, or receiver to a function.joseph_ivie
07/31/2025, 3:10 PMexpect value class ViewNode
actual value class ViewNode(val android: View) // android
actual value class ViewNode(val web: HTMLElement) // web
actual value class ViewNode(val ios: UIView) // ios
To be clear, this doesn't currently work, but it would be nice if it did.alexhelder
08/04/2025, 2:29 PMPreferences and MutablePreferences, and the context for get() should be Preferences, and the context for set(value) should be MutablePreferencesjoseph_ivie
08/07/2025, 8:33 PMcontext(clock: Clock = Clock.System) fun functionRequiringTime() = TODO()
I could see myself using this to make the common use cases straightforward while still handling tests correctly.Cies Breijs
08/08/2025, 11:04 AMAlexander Kuklev
08/12/2025, 11:32 PMval m = list.min().when { NoSuchElement -> 0 }
someExpression.when {
it < 0 -> Int.MIN_VALUE
it > 100 -> Int.MAX_VALUE
}.doOtherStuff()
Default else branch is obviously else -> it. We propose only allowing the anonymous parameter `it`; if you need to name it, use the ordinary when.
Chained `when`’s seem to be the perfect fit for rich errors where the elvis operator :? is no longer, but have great applications otherwise.Alexander Kuklev
08/12/2025, 11:53 PMHunter
08/17/2025, 3:05 PM? and elvis ?: operators? This is already kinda part of the rich error proposal, but it only works for error unions there, but could also just be useful on its own. It's essentially just syntax sugar for a monad map.
Basic example (not sold on this syntax):
sealed interface ParseResult<T> {
data class Success(val value: T) : ParseResult<T>
data class FormatError(val expected: String, val got: String) : ParseResult<Nothing>
data class Failure(val cause: Exception) : ParseResult<Nothing>
operator fun <R> question(operation: T.() -> R): ParseResult<R> =
if (this is Success) this.value.operation() else this
operator fun <R : T> elvis(operation: () -> R): T =
when (this) {
Success -> this.value
else -> operation()
}
}
fun Foo.Companion.parse(str: String): ParseResult<Foo> = //...
fun example() {
val foo: Foo = Foo.parse("hello world")?.doSomething() ?: Foo.None
}
I don't really like how the elvis overload works here, but I think it gets the idea across.mikhail.zarechenskiy
08/22/2025, 10:53 AMHunter
08/22/2025, 6:08 PMcontext(...: Foo) over and over again. What if you could create context-aliases that look like keywords? I.e.
interface ServerContext
contextalias server = context(serverContext: ServerContext)
server fun foo() { ... } // same as context(_: ServerContext) fun foo()
This one is a bit of a long-shot, and I would be open to alternatives, but something like this would be nice.Alejandro Serrano.Mena
08/27/2025, 1:21 PMelse branches.bobko
08/27/2025, 4:49 PMsuspend functions" exploration proposal.
Text
DiscussionFlorian Freitag
09/01/2025, 4:33 PMJibidus
09/09/2025, 5:19 PMfun <T> buildInstance(clazz: Class<T>): T
… but this works only with classes which declare a constructor with a specific signature signature?
In such cases, constructor declaration in interfaces (or something similar) would help to keep code robust at runtime, right?
interface Buildable {
constructor(param: Sting)
}
fun <T: Buildable> buildInstance(clazz: Class<T>): T {
return clazz.constructor("param")
}
What do you think about this idea 💡?Mikhail Vorobev
09/15/2025, 8:38 AMDerek Peirce
10/26/2025, 7:51 AMfor (i in 0 until 5) {
println(i)
}
this compiles into Java:
for(int i = 0; i < 5; ++i) {
System.out.println(i);
}
However, revising it to:
(0 until 5).forEach { i ->
println(i)
}
turns it into the vastly less efficient:
Iterable $this$forEach$iv = (Iterable)RangesKt.until(0, 5);
int $i$f$forEach = 0;
Iterator var2 = $this$forEach$iv.iterator();
while(var2.hasNext()) {
int element$iv = ((IntIterator)var2).nextInt();
int var5 = 0;
System.out.println(element$iv);
}
Could the compiler be optimized to recognize when it is creating an Iterator from a well-known Range, whether that's for forEach, forEachIndexed, all, etc., and use the more efficient for-loop instead?
Adjusting the above code to use the first form instead of the second form is trivial enough, but optimizing a call like:
(0 until 10).all { evaluatesCorrectly(it) }
ends up looking something like:
run {
for (i in 0 until 10) {
if (!evaluatesCorrectly(i))
return@run false
}
true
}
which is more efficient, but not nearly as concise.Alejandro Serrano.Mena
10/27/2025, 1:08 PMnatpryce
10/29/2025, 7:47 AMdata class Basket<Fruit>(fruit: Set<Fruit>)
And an instance of it:
val bananas : Basket<Banana>
The type checker does not allow:
val apples : Basket<Apple> = bananas.copy(fruit = listOf(apple1, apple2))
Instead, I have to call the constructor of new Basket<Apple> explicitly and copy fields from the Basket<Banana>.
What do people think about making the copy method generic for generic data classes?