-
Notifications
You must be signed in to change notification settings - Fork 363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uuid #382
Comments
As Uuid really is a base building block of data models, the package dependencies really matter. For the JVM, instead of having uuid depend on nio, it should really be the other way around! |
I do like that, by default, However, I would find it nice to have |
If I understood this correctly, only the convenience extension functions for reading from / writing to |
@axelfontaine also, what exactly do you mean by "package dependencies"? It's not like there is a maven dependency (nio is in the Java runtime). Are you talking about Java 9 modules and the |
I would prefer the name to be
Mime and UUID are both abbreviations, but the former is an acronym, and the later is an initialism.
I can see how
The visual difference between UUID/Uuid is confusing when looking at the Kotlin/Java converter helper: public fun Uuid.toJavaUuid(): java.util.UUID Shouldn't the extension
This same confusion happens with other types (I've encountered this Random/Random). But those cases are exceedingly rare, and Kotlin provides tools to easily deal with them (named imports, or typealiases, or just using the FQN.) Given that the confusion only happens in Kotlin/JVM, should other Kotlin targets have an unusual UUID name because of some other Kotlin target? Maybe the confusion be helped by introducing official type aliases? // kotlin-stdlib/src/jvmMain/kotlin/uuid/uuid-helpers.kt
typealias UuidKt = kotlin.uuid.UUID
typealias UuidJdk = java.util.UUID |
I am definitely opposed to using pronunciation as a guiding principle on casing for a few reasons:
|
I suggest to replace
This would result in
Consistency example: val uuid2 = Uuid.fromULongs(0x550E8400E29B41D4uL, 0xA716446655440000uL)
val uuid3 = Uuid.fromHexDashString("550e8400-e29b-41d4-a716-446655440000") I'd also support replacing
for the variant guaranteeing a specific format. ( |
Admittedly I prefer |
I'm against using from for parsing strings, because UUIDs are 126bit long numbers which have a representation as a string (serialized as) which can be parsed later on. |
I was looking at the compiled JS code, and I think using fromByteArray_d3r0u1_k$(byteArray) {
if (!(byteArray.length === 16)) {
var message = 'Expected exactly 16 bytes';
throw IllegalArgumentException.new_kotlin_IllegalArgumentException_f8t9r5_k$(toString_1(message));
}
return this.fromLongs_uu1aj7_k$(toLong_1(byteArray, 0), toLong_1(byteArray, 8));
} The private fun ByteArray.toLong(startIndex: Int): Long {
return ((this[startIndex + 0].toLong() and 0xFF) shl 56) or
((this[startIndex + 1].toLong() and 0xFF) shl 48) or
((this[startIndex + 2].toLong() and 0xFF) shl 40) or
((this[startIndex + 3].toLong() and 0xFF) shl 32) or
((this[startIndex + 4].toLong() and 0xFF) shl 24) or
((this[startIndex + 5].toLong() and 0xFF) shl 16) or
((this[startIndex + 6].toLong() and 0xFF) shl 8) or
(this[startIndex + 7].toLong() and 0xFF)
} will create more than 50 |
Curiosity question, is there anything preventing |
Currently, value classes can only have a single field (see #340). Based on, what would its field be?
Also, with a value class, the representation must be exactly the same on all platforms and is part of the public API, whereas with regular classes, it can be kept as an implementation detail of each platform, and change if performance problems are found. |
A small nit: on the JVM, at least, this is not true. Let's assume a 64-bit JVM running with compressed OOPs (the default).
(I included a byte array version because you wouldn't want to use a long array in general due to its abysmal representation on JS) So really no matter what you do you're allocating 32 bytes. A value class, however, will require boxing at certain points (such as when used in a generic context) which will be a 16-byte allocation each time (12-byte header + 4-byte object reference). You can validate all of this yourself using JOL. Although having written all this maybe you were referring to runtime bounds checking on the array? There's usually ways to convince the JVM compilers and ART on Android to eliminate/minimize them, but for that I'd need to break out JMH and other tools. I don't think a value class is really being considered here, so I'm not going to bother right now. |
I did mean runtime memory usage, but I forgot about padding, so you're completely right that it doesn't make a difference here. Thanks for reminding me! |
I wonder why that is, besides having to settle on a common backing field for all platforms, which might take some effort, a value class makes a lot of sense to me. |
I think the backing property type is the largest part of that discussion. It would probably mean this waiting for |
This does make sense to me, given that the emphasis is on conversion to the specific type. When considering the conversion to Java's representation of the Universally Unique Identifier (UUID), the name |
Sorry I got a little bit late to this KEEP discussion, but another thing I just raised in https://youtrack.jetbrains.com/issue/KT-31880#focus=Comments-27-10312473.0-0 is the name choice for the I found out about this new type looking for a UUID v7 Kotlin implementation, actually, and I'm willing to eventually even contribute with some code as I had to roll my own too many times already. If/when we do have a v7 generator function, how are we calling it? Why don't we just use the The KEEP mentions:
While this is true, I think we are getting things backwards here. In my experience with UUIDs, I think the lack of a standard trustworthy way of generating other versions of UUIDs other than v4 is the reason many people end up using v4 more than they "should". For databases, for example, the impact of using v4 instead of v7 on index re-balancing is at least non-negligible (quick example, there are many more). Not saying v7 or any other version should be a blocker for a initial release, but I think we should aim for excellence in the standard library (as the team has been doing, I think the Kotlin standard library is great) and that would include 2 things in regards to UUIDs:
|
For |
I understand the concern about adopting a consistent naming convention for the future generator functions.
Python, Go, and Rust can generate v1-v5 UUIDs, and we have observed a similar trend regarding UUID version popularity in these languages as well. While I share your enthusiasm for v7 and believe it will gain wider adoption, as described in the KEEP, we see technical limitations in correctly generating it within the stdlib. I believe that database systems and frameworks are the appropriate places for generating v7, as they can handle clock rollbacks and guarantee the monotonicity and consistency of generated UUIDs within the system. Could you please elaborate on how you would handle clock rollbacks and system restarts within the stdlib ? Or do you think ensuring monotonicity within a single program session would be enough? |
In the KEEP, it does not specify in-place what "standard" means, but just: "Returns the standard string representation of this uuid."
This contract would deviate from learned expectations. It seems unusual to use
Given:
Why would there be a higher risk compared to the level of possible confusion we could always presume? I'd expect even more confusion with |
Please find the full documentation for |
I'm not trying to convince us to implement v7 right now, I'd like that but I understand we shouldn't spend time now if there's not enough demand. I just want to make sure we use an extensible and coherent naming convention and those links you posted are just another argument against Python: Go created a If I recall correctly, JS and PostgreSQL also have v4 in their method names.
Allow me to politely disagree on this, @qurbonzoda. If a developer decides to use UUIDs without basic knowledge about what that type is, there's very little we can do for them. Also, if anything, that's an argument against If you by any chance don't know how to generate a UUID and you do
The entire point of using UUIDs is to avoid (or at least having the option of not) generating them inside the database. I understand there are challenges, but as we just saw in the links above many major languages already provide them.
In my experience clock rollbacks are not critical because we still have a fair bit of the payload being random. Even without monotonicity and rollback avoidance guarantees, v7 is very useful to avoid major and frequent index re-balances in the database. |
Is there any reason why there are no |
Currently, the stdlib project does not have separate source sets for different Kotlin/Native targets. This is due to how the Kotlin/Native stdlib is built and published. When it becomes possible to have an Apple-specific source set, we will include such conversion functions as well. |
I just read the rfc9562 and I found these sections. Regarding sorting:
https://www.rfc-editor.org/rfc/rfc9562.html#section-6.11 In Java/Kotlin, the interface to support sorting is Regarding the function/factory names for different versions: |
I support @bcmedeiros argument of implementing various Where I do disagree tho, it is the removal of standard non-parametrized |
Another thing after I switched a project to kotlin.uuid.Uuid is the parsing function in combination with kotlinx-serialization (here Json). Uuid provides two parsing functions: Also, the KEEP mentions possible bracket parsing support in the future. Do you plan to add another |
I don't want to switch to this new implementation of KMP UUID until JS efficiency is addressed. In addition, I second @hfhbd 's recommendation to implement |
I have added a paragraph about introducing cc: @hfhbd, @OliverO2, @joffrey-bion |
I have also added a paragraph about making Kotlin |
@UnknownJoe796, could you please share your use cases where a Comparable Uuid would enable a usage or improve the user experience? @hfhbd has reported a YouTrack issue because Anyone's input would be greatly appreciated. |
While it may seem counterintuitive for UUIDv4, Comparable is an absolute must for UUIDv7 which is inherently sortable and widely used as a database ID. Even if it won't be produced by Kotlin's UUID at first (a shame, but can be fixed later), it will be read into it from day 1! |
@axelfontaine, it would be very helpful if you could share the use case you have in mind for a |
Multiple formats
Quoting from the added paragraph:
If a conversion accepting multiple input formats is intended, I'd suggest to document it as being
NamingOn naming: As noted above, and previously, I'm still concerned about deteriorating API quality in the Kotlin stdlib with each additional introduction of an imperative name like Example: Even though generally aware of a string's immutability, I found myself introducing an error being misled into assuming that We should aim for less of this confusion and poor readability, not more. Mapped type
I consider it a good idea to keep Kotlin Uuid independent (and not a Java-mapped type). Using the Java type would tie Kotlin to a limiting and buggy Java implementation. I'd favor better quality (avoiding footguns) and lower complexity over convenience with limited gains (I'd not expect many use cases requiring Java/Kotlin UUID conversions all over the place). |
In-memory test data generation, subject to the same ordering as what a DB would return is an obvious one.
A separate Comparator will absolutely work. It's just more boilerplate, not as easily discoverable and error prone (must be passed every single time). A Comparator is primarily useful when multiple sorting orders are common. This is not the case for a UUID. Either one doesn't care, or it's lexical. Nothing else. @qurbonzoda Why all the push-back? Please help me understand your perspective here as I really don't get it. A UUID is very much a primitive-like low level building block and every single other one in this category (numbers, strings) is Comparable for good reason. |
Could you please elaborate on this? You would greatly help me understand the use case if you could provide a snippet showing how the code would look with the current design versus if the
I agree that lexical ordering is the most sensible in most cases. However, UUID v1 timestamp comparisons can be found in the wild. Additionally, UUIDs allow for custom payloads, for which different sorting criteria might be more appropriate. Please note that the Java UUID implementation of
I have provided our rationale behind the decision not to implement
|
I'm not the author of this, so I don't know the details, but it seems the current implementation has a few issues on WASM: InsertKoinIO/koin#2046 |
@qurbonzoda Thank you for detailing your perspective. I am fully aware balancing the various interests to come up with a good solution is no easy task.
In order to quickly model various scenarios for our tests, we have fake implementations of services that won't be backed by a DB, but will instead generate test data for the case we need (often relying on tools like DataFaker). Our database has IDs in UUIDv7 format and these fake implementations generate those too and the collections they return should be in the same order as the ones from the DB. Again, this can be solved with Comparator too, it's just clumsier.
Being Comparable, does not preclude the use of specific Comparator implementations when they are more appropriate than the default implementation. |
Thanks @CLOVIS-AI. The issue is fixed now and will be included in Kotlin 2.1.20: JetBrains/kotlin@57581ec |
This issue is for discussion of the proposed
Uuid
API. The full text of the proposal is here.The API is already available in Kotlin 2.0.20-Beta2 and later, and is marked with
@ExperimentalStdlibApi
.The text was updated successfully, but these errors were encountered: