eygraber
07/16/2024, 5:51 PMit has the side effect of users being able to make their pre-release versions available to their communities during ongoing developmentI feel like that's a very valuable tool, since it makes it very easy for the community to verify that something works, or adopt changes before a release is made. It's probably not the best solution for this, and a full release pipeline would probably be "better", but I think that's unfeasible for small projects that don't have the manpower to setup and manage those types of solutions.
Slackbot
07/19/2024, 5:55 PMarnaud.giuliani
07/24/2024, 7:13 AMmbonnin
07/25/2024, 3:48 PMMETA-INF
folder of the jar for verification purposes (doc). While it’s probably technically OK (the file is small), it still feels a bit weird. It’s adding noise to the binary for no apparent good reason. The file could be put in another artifact or sounds like we could use GPG signatures for that.
Any thoughts about this? Is that common practice?Sebastian Sellmair [JB]
08/09/2024, 7:37 PMEmil Kantis
08/19/2024, 7:00 AMLoïc Lamarque
09/18/2024, 9:21 AMOleg Yukhnevich
10/03/2024, 10:23 AMAlex Styl
10/18/2024, 3:35 AMPiotr Krzemiński
10/18/2024, 6:45 AMcopy
and the change related to it that is going to be made in Kotlin 2.1.0 (ref). We do have some thoughts, but I wanted to consult it with wider group of people before we decide on something.
In the library github-workflows-kt, we generate certain data classes on the server side, and the users consume them via Kotlin Scripting. Here's a simple example of such generated class: SimpleActionWithRequiredStringInputs.kt. Notice what is done with the constructors: there are two, and the primary constructor is made private. It's because we want to enforce using named arguments when instantiating the class. To achieve it, we use a kind of hack with vararg pleaseUseNamedArguments: Unit
as the first arg, and it's done in the secondary constructor because Primary constructor vararg parameters are prohibited for data classes.
- that's why we also make the primary one private.
Now, the whole problem revolves around the fact that our users may already depend on the existence of the public copy
method. It's going to become private starting Kotlin 2.1.0. We want to keep providing this API for the users. These ideas came to our minds, among others:
1. implement copy
ourselves
◦ won't work since there would be conflicting overloads
2. ensure that named arguments are used in a different way, e.g. in runtime via reflection (performance-wise, it's OK), then we could make the primary constructor public
◦ is it even possible? named/positional arguments distinction exists probably only in compile time
3. make the classes regular (non-data
) and implement everything that data classes provide on our own, with the ultimate control over visibility
◦ well, it would probably work, but it's complex and I'm trying to see if there's another way 😄
So basically, the problem boils down to this: data classes (or data-like classes) with enforcing named arguments upon creation, working in Kotlin 2.1.0+.
Our discussion so far: https://kotlinlang.slack.com/archives/C02UUATR7RC/p1724584851609139
Any novel take on this problem is greatly appreciated!
CC @VampireMatthew Feinberg
10/21/2024, 4:39 AMexpect fun
(part of our library implementation) is being called on Android builds, but only when our library is included as a dependency (in the "sample" app, it works fine)! I have no idea where to start to try to diagnose this problem. Any pointers would be greatly appreciated. If it matters, the function in question is a composable function:@Composable
internal expect fun PlatformRenderView(...)
settings.gradle.kts
we have include(":sample:composeApp")
and include(":lib")
). When running the sample app, everything works fine on both Desktop and Android targets. However, when we publish the lib
internally (using maven-publish
) and try to use it as a dependency in another multiplatform project, the Desktop build works fine, but whenever we try to call a expect
function on the Android built, it tries to use the desktop actual
rather than the Android actual
.Shreyash Kore
10/25/2024, 9:05 AMCLOVIS
10/30/2024, 8:59 PMmyLib.foo(FooOptions { … })
myLib.bar(BarOptions { … })
I also have many options that are common between multiple types.
What's the best way to avoid duplicating all common options between all types?
So far, my best candidate is:
interface CommonOptions {
fun option1(…)
fun option2(…)
}
class FooOptions : CommonOptions {
private var option1 …
private var option2 …
private var option3 …
override fun option1(…) { option1 = … }
override fun option2(…) { option2 = … }
fun option3(…) { option3 = … }
}
class BarOptions : CommonOptions {
private var option1 …
private var option2 …
private var option4 …
override fun option1(…) { option1 = … }
override fun option2(…) { option2 = … }
fun option4(…) { option4 = … }
}
and, sure, it works, but it's very verbose :/Soren Roth
11/01/2024, 6:52 PMZach Klippenstein (he/him) [MOD]
11/01/2024, 8:49 PMmika
11/04/2024, 9:16 AMArray.contains(_:)
come with documented complexity, which I find very useful. I really miss having something similar in Kotlin.
Here’s why I believe it would be valuable:
1. It enhances the development experience.
2. It promotes better, more efficient code.
3. It serves as a helpful form of documentation.
4. It centralizes the work, saving every developer from having to research complexities individually.
One possible approach could be to automate the calculation of time complexity empirically, using performance measurements across different n
values and object types (based on platform and common use cases).
Please let me know what you think—I’d be happy to assist with this.
Best regards,
MikaMikael Ståldal
11/12/2024, 8:42 AMdominicmarmion
12/04/2024, 12:44 PMwakingrufus
12/08/2024, 6:49 PMCLOVIS
12/11/2024, 2:28 PMDan Rusu
12/18/2024, 7:08 PM@UnsafeVariance
? I'm trying to decide the best approach for the Immutable Arrays library.
Immutable Arrays are covariant so you can pass an ImmutableArray<Employee>
to functions that expect ImmutableArray<Person>
when Employee
extends Person
.
With ImmutableArray<T>
, most operations produce T
but there are a handful that consume `T`:
• contains(element: T)
• indexOf(element: T)
• lastIndexOf(element: T)
• getOrElse(index: Int, default: (Int) -> T)
There are also a couple that might be more dangerous for ensuring type safety if T
was declared as `in T`:
• plus(element: T)
// creates a new Immutable Array with the element appended
• plus(elements: ImmutableArray<T>)
// creates a new Immutable Array with the elements appended
Attempting to add any of these methods results in an error: Type parameter 'T' is declared as 'out' but occurs in 'in' position
I worked around this problem by turning these methods into extension functions which utilize allowed methods:
fun <T> ImmutableArray<T>.contains(element: T): Boolean {
return any { it == element }
}
fun <T> ImmutableArray<T>.indexOf(element: T): Int {
forEachIndexed { index, value -> if (value == element) return index }
return -1
}
//...
The extension functions require additional imports (which IntelliJ nicely auto-suggests) so I'm wondering whether to continue with the extension function approach for these handful of operations or whether to make them regular methods by using @UnsafeVariance
to avoid the imports.
Searching in YouTrack, I get the impression that Kotlin is moving away from using @UnsafeVariance
but I'm not sure if I'm interpreting that correctly:
• https://youtrack.jetbrains.com/issue/KT-57603/Prohibit-using-UnsafeVariance-for-invariant-type-parameter
• https://youtrack.jetbrains.com/issue/KTLC-72/K2-Stop-relying-on-the-presence-of-UnsafeVariance-using-for-contravariant-parameters
I noticed that kotlinx immutable collections use @UnsafeVariance
for their persistent abilities. Does anyone know the official direction that the Kotlin team is planning for @UnsafeVariance
or what the officially recommended approach is for dealing with these types of variance scenarios?Marcin Mycek
12/20/2024, 9:10 AM# gradle.properties
kotlin.native.enableKlibsCrossCompilation=true
We are looking for any unknown limitations and problems we need to address. We would appreciate your feedback if you encounter any in this YouTrack issue!
*Cross-compilation has some limitations. You still need to use a Mac machine if:
• Your library has a cinterop dependency.
• You have CocoaPods integration set up in your project.
• You need to build or test final binaries for Apple targets.
For cinterop dependencies we are tracking this in this YouTrack issue and would love to hear what's your use case there!Soren Roth
01/13/2025, 11:49 PMarnaud.giuliani
02/18/2025, 4:02 PMIvan Carracedo Asensio
02/26/2025, 11:38 AMCLOVIS
03/06/2025, 3:55 PMinterface FooA {
fun foo(name: String, value: Int)
}
interface FooB {
fun foo(value: Int)
}
The two interfaces represent two different ways of interacting with a single entity. In some contexts, the library provides an instance of the first interface, and in some contexts, the library provides an instance of the second interface. However, since they are both used to interact with a single entity, it's more convenient for the library author to implement a single instance that can be viewed as both:
private class FooImpl : FooA, FooB {
override fun foo(name: String, value: Int) {}
override fun foo(value: Int) {}
}
So far, everything is good I think.
I think however there is a risk that a user would use a cast to change their access context even if it's not allowed.
withFooA { // provided by the library
it as FooB // will succeed because FooImpl does implement FooB
it.foo(4) // illegal call to FooB.foo in the context of FooA, but will compile and run
}
Should this be considered a risk? Should I split the implementations of the two interfaces to stop this usage? Or should I consider that this is bad code anyway and I should ignore the fact that users could write it?Cosmin Mihu
03/09/2025, 5:34 AMCLOVIS
03/21/2025, 9:15 PMTomer
04/04/2025, 2:10 PM@UnsafeVariance
. If I am defining some Container<out T>
class and I want one of its methods to return Optional<T>
(for Java users), then is it safe/reasonable to do Optional<@UnsafeVariance T>
? I don't want to do Optional<out T>
since that will end up being Optional<? extends T>
for Java users, which is annoying to work with.
I think using @UnsafeVariance
here makes sense because Optional
is an immutable container so you can only get T
out of it; you can't put a new T
into an existing Optional<T>
. It's just that Java obviously does not define Optional
with out T
at it's declaration (since it's not Kotlin)
Am I making sense? Am I missing anything here?Fudge
04/21/2025, 5:34 PM@Sample
? Usually samples are not part of the main source set, so doesn't that mean samples will always not resolve?