Kotlin: Hashcode of chars is same as ASCII value - kotlin

I noticed that the hashcode of Char-values is exactly the ID they have in ASCII, for example:
println('a'.hashCode()) //is 97
Is this true by contract and where can I see the implementation for this? The class Any.kt doesn't contain the implementation and Char.kt does neither.

I noticed that the hashcode of Char-values is exactly the ID they have in ASCII […]
That is impossible. ASCII only has 128 values, but Kotlin Char has 65536, so clearly, a Char cannot have their ASCII value as their hashcode, because 99.8% of them don't have an ASCII value.
Is this true by contract
No, it is not. The contract for kotlin.Char.hashCode() is:
fun hashCode(): Int
Returns a hash code value for the object. The general contract of hashCode is:
Whenever it is invoked on the same object more than once, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
If two objects are equal according to the equals() method, then calling the hashCode method on each of the two objects must produce the same integer result.
That is the whole contract. There is nothing about a relationship with ASCII.
and where can I see the implementation for this? The class Any.kt doesn't contain the implementation and Char.kt does neither.
I am assuming types like kotlin.Char or kotlin.Int are not actually implemented as Kotlin objects but as compiler intrinsics for performance reasons. For example, I would expect 42 to be a JVM int on the JVM platform and an ECMAScript number on the ECMAScript platform, and not implemented as a full-blown object with object header, instance variable table, class pointer, etc.
As it so happens, Kotlin's contract for hashCode() matches the contract for pretty much every other language as well, so I would expect that they as much as possible re-use the underlying platform's implementation. (In fact, I would suspect that is precisely the reason for designing the contract this way.)
Even for Kotlin/Native, it makes sense to map kotlin.Int to a native machine integer int_fast32_t or int32_t type.

Related

Why does casting to a generic work without an instance of that type?

I've created 2 kotlin methods: one to check a type and another to cast an object. They look like:
fun Any?.isOfType(type: Class<*>): Boolean{
return type.isInstance(this)
// return `this is T` does NOT work.
}
and
fun <T> Any?.castToType(): T {
return this as T
// Works, albeit with a warning.
}
I've read some posts on generics and erasures, but I can't get over what seems to be a discrepancy.
Why is it that checking for the type of an object cannot be done with generics, but casting to a generic can?
The question is why:
fun <T> Any?.castToType() = this as T // compiles with warning
"hello".castToType<Int>()
"works" but this won't even compile:
fun <T> Any?.isOfType() = this is T // won't compile
"hello".isOfType<Int>()
Actually both don't really work. In both cases the type is erased at runtime. So why does one compile and the other doesn't?
this is T cannot work at runtime since the type of T is unknown and thus the compiler has to reject it.
this as T on the other hand might work:
"hello".castToType<Int>() // no runtime error but NOP
"hello".castToType<Int>().minus(1) // throws ClassCastException
2.0.castToType<Int>().minus(1) // no runtime error, returns 1
In some cases it works, in others it throws an exception. Now every unchecked cast can either succeed or lead to runtime exceptions (with or without generic types) so it makes sense to show a warning instead of a compile error.
Summary
unchecked casts with generic types are no different from unchecked casts without generic types, they are dangerous but a warning is sufficient
type checks with generic types on the other hand are impossible at runtime
Addendum
The official documentation explains type erasure and why is-checks with type arguments can't succeed at runtime:
At runtime, the instances of generic types do not hold any information about their actual type arguments. The type information is said to be erased. For example, the instances of Foo and Foo<Baz?> are erased to just Foo<*>.
Due to the type erasure, there is no general way to check whether an instance of a generic type was created with certain type arguments at runtime, and the compiler prohibits such is-checks such as ints is List or list is T (type parameter)
(https://kotlinlang.org/docs/generics.html#type-erasure)
In my own words: I can't check whether A is B if I don't know what B is. If B is a class I can check against an instance of that class (that's why type.isInstance(this) works) but if B is a generic type, the runtime has no information on it (it was erased by the compiler).
This isn't about casting vs checking; it's about using generics vs class objects.
The second example is generic; it uses T as a type parameter. Unfortunately, because generics are implemented using type erasure, this means that the type isn't available at runtime (because it has been erased, and replaced by the relevant upper bound — Any? in this case). This is why operations such as type checking or casting to a type parameter can be unsafe and give compilation warnings.
The first example, though, doesn't use a type parameter; instead, it uses a parameter which is called type, but is a Class object, representing a particular class. This is a value which is provided at runtime, just like any other method parameter, and so you can call methods such as cast() and isInstance() to handle some type issues at runtime. However, they're closely related to reflection, and have some of the same disadvantages, such as fragility, ugly code, and limited compile-time checks.
(Kotlin code often uses KClass objects instead of Java Class objects, but the principle is the same.)
It may be worth highlighting the difference between class and type, which are related but subtly different. For example, String is both a class and a type, while String? is another type derived from the same class. LinkedList is a class, but not a type (because it needs a type parameter); LinkedList<Int> is a type.
Types can of course be derived from interfaces as well as from classes, e.g. Runnable, or MutableList<Int>.
This is relevant to the question, because generics use type parameters, while Class objects represent classes.

How to restrict enums in Kotlin?

I have an enum with many values; error codes for example, or some official list of coded values. In my application, I have several functions where only a subset of those values is admissible. How can I derive restricted enums that contain only a subset of the original enum?
For example, I have an externally provided dictionary of error codes that model as enum:
enum class ApiError(val: errorCode: Int) {
INCORRECT_CHARACTER(1),
MISSING_VALUE(2),
TOO_SMALL(3),
TOO_LARGE(4)
}
In one function call, only the TOO_SMALL and TOO_LARGE errors may result, in another only INCORRECT_CHARACTER or MISSING_VALUE. Instead of defining two new enums for these particular error return values, I would like both to somehow reference the complete enum with all error codes.
To be more precise: Assume I have a function fun handleError(error: ApiError); inside this function, I want to be able to write an exhaustive when pattern match that covers all enum cases. However, I also want to be able to pass an argument of a restricted enum type to that same function, where that restricted type can take on only a subset of the enum values, as in the example above.
What comes to mind (but does not work in Kotlin) would be to subclass the ApiError enum while restricting the admissible values in each subclass. Is there a Kotlin solution that does something similar?
The opposite question – to subclass an enum for extension – has been discussed here at length. As far as I understand, the objections there do not apply when restricting the potential enum values.
And just for curiosity: I suppose the above question is some concrete and utterly misspecified version of a some type theoretical problem. Can someone provide pointers to the proper theory and terminology?
What comes to mind (but does not work in Kotlin) would be to subclass the APIError enum while restricting the admissible values in each subclass. Is there a Kotlin solution that does something similar?
Yes, if you need to express a hierarchy, you could use sealed class/interface hierarchies with objects as leaves.
sealed class ApiError(val code: Int) {
object IncorrectCharacter : ApiError(1)
object MissingValue : ApiError(2)
}
sealed class SizeError(code: Int): ApiError(code) {
object TooSmall : SizeError(3)
object TooLarge : SizeError(4)
}
What you lose here compared to enums is the ability to list all possible values using ApiError.values(). But in this case it might not be an issue.
Also it might not be ideal to serialize (and even more so, deserialize), depending on which serialization library you're using.

Why is the key type parameter of a Kotlin Map invariant?

The Map interface in Kotlin (using V1.6.21) has a signature of
interface Map<K, out V>
Why is K invariant instead of covariant (out K)?
The documentation of type parameter K says:
The map is invariant in its key type, as it can accept key as a parameter (of containsKey for example) and return it in keys set.
However, interface Set is covariant in the element type, so the the last part ("return it in keys set") is not applicable, at least not immediately.
Further, the type parameter K is used only at occurrences where the map state is not modified, for lookup purposes (methods containsKey, get, getOrDefault). At these places, isn't it safe to use #UnsafeVariance? After all, that same technique was employed to Map's value type parameter V, for example in containsValue, to allow making V covariant.
My guess would be that using a Map<KSubtype, V> as a Map<KSupertype, V> (where KSubtype : KSupertype) does not really make a lot of sense because the former, by construction, cannot contain entries with keys other than KSubtype.
So a proper implementation should return null from all calls to get(kSupertype) as well as return false from those to containsKey(kSupertype).
In the case of Set<out E> it's only the contains function that needs unsafe variance, and Map would also require unsafe variance on get. This might have been too much of a peculiarity to support, compared to the value of supporting the use case.

Why does lateinit work on Object type but not primitive type?

This answer says that Object types use the null value on lateinits of Object type. Can someone elaborate on this? What do they mean by "uses the null value"?
Furthermore it says "For primitive types, there is no such value" - why is there no
On the JVM, which was historically the first platform targeted by Kotlin, there is a distinction between the primitive types and classes, or object types.
They have different runtime representations: a primitive value is stored directly in the field, which can only hold one of the corresponding primitive type values (e.g. only true and false for boolean) and has no special representation for a missing value. In comparison, a class-typed field stores an indirect reference to an instance that is allocated somewhere in the heap, and a class-typed field can hold a special null reference that doesn't point to any instance.
The Kotlin lateinit properties are compiled to a single field and they internally use the null value to indicate that the property has not yet been initialized. As primitive-typed JVM fields can't have a null value, Kotlin doesn't allow lateinit properties of types that are normally mapped to Java primitives, as that would require a different representation, and no acceptable solution existed, as the other answer says.
Instead, you can use by Delegates.notNull() to achieve similar behavior with the mapped types.

dlang inheritance design for types passed between threads

I'm writing a multithreaded program in the D programming language, but am pretty new to the language. There is a restriction on types passed between threads using the Tid.send() and receive[Only]() APIs in the std.concurrency package that they must be value types or must be constant to avoid race conditions between the sender and receiver threads. I have a simple struct Message type that I have been passing by value:
enum MessageType {
PrepareRequest,
PrepareResponse,
AcceptRequest,
Accepted
}
struct Message {
MessageType type;
SysTime timestamp;
uint node;
ulong value;
}
However, some MessageTypes don't have all the fields, and it's annoying to use a switch statement and remember which types have which fields when I could use polymorphism to do this work automatically. Is using an immutable class hierarchy recommended here, or is the approach I'm already using the best way to go, and why?
Edit
Also, if I should use immutable classes, what's the recommended way to create immutable objects of a user-defined class? A static method on the class they come from that casts the return value to immutable?
As a rule of a thumb, if you have a polymorphic type hierarchy, classes are the tool to use. And if mutation is out of the question by design, immutable classes should do the trick efficiently.
Great presentation from DConf2013 by Ali has been published recently : http://youtu.be/mPr2UspS0fE . It goes through topic of usage of const and immutable in D in great detail. Among the other good stuff it suggests to use
auto var = new immutable(ClassType)(...); syntax for creating immutable classes. All initialization goes to constructor then and no special hacks are needed.