https://kotlinlang.org logo
#stdlib
Title
# stdlib
m

Marc Knaup

09/26/2019, 7:27 AM
Can we kotlinify Java’s
Objects.hash(foo, bar, baz, …)
to something like this?
hash { foo x bar x baz x … }
Just the boxing is a little tricky as well as getting it to work with just a single non-
Int
value without introducing boxing. Implementation:
Copy code
inline fun hash(block: HashScope.() -> Int) =
	HashScope.block()

object HashScope {

	inline infix fun Any?.x(hashable: Any?) =
		(31 * hashCode()) + hashable.hashCode()

	inline infix fun Any?.x(hashable: Int) =
		(31 * hashCode()) + hashable

	inline infix fun Int.x(hashable: Any?) =
		(31 * this) + hashable.hashCode()

	inline infix fun Int.x(hashable: Int) =
		(31 * this) + hashable
}

class Example(val foo: String, val bar: List<Any>?, val baz: Int) {

	override fun hashCode() =
		hash { foo x bar x baz }
}
j

jw

09/26/2019, 12:02 PM
What's the advantage over just
hashOf(vararg args: Any?)
which seems more idiomatic than a somewhat-cryptic DSL? Then you can add an intrinsic in the compiler, similar to what's being explored in javac.
m

Marc Knaup

09/26/2019, 12:04 PM
Java’s isn’t multiplatform. Also, doesn’t
Objects.hash()
cause a lot of wrapping (primitives/inline classes)? + additional array and ArrayList allocation. Or are calls replaced by something intrinsic at runtime?
Also intrinsic would need compiler support. My suggestion would be pure Kotlin within stdlib.
j

jw

09/26/2019, 12:06 PM
Have you observed the boxing to be a problem in practice?
Mine also is a pure Kotlin suggestion that could be aliases to the JDK version for the JVM. The intrinsic is only for increasing performance, probably through invoke dynamic.
m

Marc Knaup

09/26/2019, 12:09 PM
I can only judge from the Kotlin decompiler in IntelliJ that a lot of wrapping and one array allocation would occur. I don’t know whether that will actually disappear at runtime.
m

marcinmoskala

10/06/2019, 6:26 PM
@Marc Knaup here is a simple and multiplatform implementation. Still thinking about the name though 🤔 @jw What do you think?
Copy code
override fun hashCode(): Int =
    hashCodeFrom(timeZone, millis)

inline fun hashCodeFrom(vararg values: Any?) =
    values.fold(0) { acc, value ->
        (acc * 31) + value.hashCode()
    }
2 Views