How does EnumClass.values() work in Kotlin? - kotlin

How does EnumClass.values() work in Kotlin?
I mean will it create new Array every time, or it is lazy evaluated static, or something else?

While not 100% sure, I assume that in Kotlin (as well as in Java) Enum.values() method is generated by the compiler:
The compiler automatically adds some special methods when it creates
an enum. For example, they have a static values method that returns an
array containing all of the values of the enum in the order they are
declared. This method is commonly used in combination with the
for-each construct to iterate over the values of an enum type.
From the JLS:
/**
* Returns an array containing the constants of this enum
* type, in the order they're declared. This method may be
* used to iterate over the constants as follows:
*
* for(E c : E.values())
* System.out.println(c);
*
* #return an array containing the constants of this enum
* type, in the order they're declared
*/
public static E[] values();
This method returns new array every time.
The point is that an array can't be constant in Java: it values can be modified, so you can't share the same array and have to give a new one on every access to guarantee that the array hasn't been changed.
Simple test:
enum class MyEnum { CAT, DOG }
val a = MyEnum.values()
val b = MyEnum.values()
println("${a === b}") // >>> false
a[0] = MyEnum.DOG
println(a.joinToString()) // >>> [DOG, DOG]
println(MyEnum.values().joinToString()) // >>> [CAT, DOG]

Related

Kotlin Native Initialize Array of Struct

In Kotlin/Native, what is the correct way to create and initialize an array of a structure? My code interfaces with a C library that defines the relevant structures as:
typedef struct VkDeviceQueueCreateInfo {
...
} VkDeviceQueueCreateInfo;
typedef struct VkDeviceCreateInfo {
...
uint32_t queueCreateInfoCount;
const VkDeviceQueueCreateInfo* pQueueCreateInfos;
...
} VkDeviceCreateInfo;
I've created wrapper classes DeviceQueueCreateInfo and DeviceCreateInfo. The Kotlin bindings are generated as classes inheriting from CStructVar and used like this:
class DeviceQueueCreateInfo(...) {
// Allocates in `scope` and fills a `VkDeviceQueueCreateInfo`
fun toRaw(scope: MemScope): VkDeviceQueueCreateInfo = ...
}
class DeviceCreateInfo(val queueCreateInfos: List<DeviceQueueCreateInfo>) {
// Allocates in `scope` and fills a `VkDeviceCreateInfo`
fun toRaw(scope: MemScope) = with(scope) {
alloc<VkDeviceCreateInfo>().also {
it.queueCreateInfoCount = queueCreateInfos.size.toUInt()
it.pQueueCreateInfos = ??? // Allocate array of struct in `scope`
}
}
}
I've added a ??? to the code to show where I'm having trouble. Kotlin NativePlacement has allocArray<T>(length: Int), so that was obviously my first stop:
it.pQueueCreateInfos = allocArray(queueCreateInfos.size)
And then to initialize them I tried:
it.pQueueCreateInfos = allocArray<VkDeviceQueueCreateInfo>(queueCreateInfos.size)
.also { arr ->
queueCreateInfos.forEachIndexed { index, x -> arr[index] = x.toRaw(scope) }
}
However, this fails to compile with error No set method providing array access at arr[index] = x. I wrote the following code which compiles and runs as expected:
val floats = listOf(1f, 2f, 3f)
allocArray<FloatVar>(floats.size).also { arr ->
floats.forEachIndexed { index, x -> arr[index] = x }
}
The code is identical apart from the type used, leading me to believe that I was perhaps trying to assign to an rvalue. I went looking for VkDeviceQueueCreateInfoVar only to find this:
Also, any C type has the Kotlin type representing the lvalue of this type, i.e., the value located in memory rather than a simple immutable self-contained value. Think C++ references, as a similar concept. For structs (and typedefs to structs) this representation is the main one and has the same name as the struct itself, for Kotlin enums it is named ${type}Var, for CPointer it is CPointerVar, and for most other types it is ${type}Var.
This states that for structs, the lvalue representation has the same name as the struct (no Var suffix)... so VkDeviceQueueCreateInfo should represent an assignable lvalue, and I'm confused as to why I am unable to assign values to my array. It occurs to me that Kotlin's assignment does something very different to a C assignment, but I had assumed there would be an idiomatic way to perform a structure assignment.
I've looked through the other overloads and methods in NativePlacement to find one that allows me to initialize the values in the newly created array, and I found allocArray<T>(length: Long, initializer: T.(index: Long)->Unit), but this seems to suffer from the same problem.
How do I allocate and initialize an array of structures through cinterop?

Get constants, functions, and protocols from global scope by name

Background
I'm implementing an interface to allow JavaScript to call Objective-C APIs. I'm writing my code in Obj-C++, so can equally use Obj-C or C++ approaches.
Given a string to look up, such as #"NSObject", it's possible to retrieve the class by that name:
// Where `lookupString` is an NSString* such as #"NSObject".
Class clazz = NSClassFromString(lookupString);
I would similarly like to be able to retrieve constants, functions, enums (all data types, really) from the global scope. There are many of these, for example in Foundation:
// 1) A constant (or standalone enumerated value)
// #see https://developer.apple.com/documentation/foundation/1497293-string_encodings/nsasciistringencoding?language=objc
NSASCIIStringEncoding = 1
// 2) An actual enum
// #see https://developer.apple.com/documentation/foundation/nsstringencodingconversionoptions/
typedef enum {
NSAllowLossyEncodingConversion = 1,
NSExternalRepresentationEncodingConversion = 2
} NSStringEncodingConversionOptions;
// 3) A function
// #see https://developer.apple.com/documentation/foundation/1395298-nsstringfromprotocol?language=objc
NSString * NSStringFromProtocol(Protocol *proto);
// 4) A protocol
// #see https://developer.apple.com/documentation/foundation/nsurlconnectiondatadelegate?language=objc
#protocol NSURLConnectionDataDelegate
I am aware of these other obj-c runtime utilities:
NSSelectorFromString (does this solve case #3?)
NSProtocolFromString (clearly solves case #4)
Question
Can all four cases be solved? In other words, how can each of these data types be retrieved from the global scope (or in the scope of an explicitly-named library) at runtime by name alone?

Kotlin Numeric Literals

I noticed that I can convert a double value into an integer like this.
var array = kotlin.arrayOfNulls<Int>(10)
for( i in array.indices ){
array[i] = ( Math.random().toInt() )
}
If Math.random() returns a double value, how can a double value have a method named toInt()? Are numerical values also objects?
Yes, instances of numeric types are Kotlin objects. Quoting from the Kotlin docs:
In Kotlin, everything is an object in the sense that we can call member functions and properties on any variable. Some types are built-in, because their implementation is optimized, but to the user they look like ordinary classes.
In practice, non-nullable instances (e.g. Double as opposed to Double?) are represented under the hood with JVM primitives.
In Java, any object that extends Number has the ability to invoke intValue. I would presume that Kotlin is exposing that API there.
The Kotlin compiler aims to use primitives as much as possible. This means using primitives unless a variable is nullable or has to be boxed because generics are involved. (Docs)
In the case of these conversion functions (.toInt(), .toLong(), etc.), the variables that these functions are called on will be primitives, and simple casts will be used on them in the bytecode. So there's no boxing happening here, these are still primitives, but you can call "functions" on them as syntactic sugar.
Math.random().toInt() // Kotlin
(int) Math.random(); // Generated bytecode decompiled to Java
In case an otherwise primitive value is assigned to a nullable variable, such as in your case (assigned to an array element which is of type Int?), it will be boxed using a valueOf call at the assignment:
val n: Int? = 25
Integer n = Integer.valueOf(25);
So your specific assignment will be a combination of the two above examples, and will translate like this:
array[i] = Math.random().toInt()
array[i] = Integer.valueOf((int) Math.random());
In case you're interested in a simpler replacement for your example code:
You can use an IntArray (primitive array, int[] in Java) instead of an Array<Int> (array of boxed values, Integer[] in Java). You can also initialize it in the constructor's second parameter using a lambda.
var array = IntArray(10) { Math.random().toInt() }
This is roughly equivalent to this Java code:
int[] array = new int[10];
for (int i = 0; i < 10; i++) {
array[i] = (int) Math.random();
}

Is Kotlin "pass-by-value" or "pass-by-reference"?

As I know Java is pass-by-value from this post. I am from Java background I wonder what Kotlin is using for passing values in between. Like in Extensions or Methods etc.
Every time I hear about the "pass-by-value" vs "pass-by-reference" Java debate I always think the same. The answer I give: "Java passes a copy (pass-by-value) of the reference (pass-by-reference)". So everyone is happy. I would say Kotlin does the same as it is JVM based language.
UPDATE
OK, so it's been a while since this answer and I think some clarification should be included. As #robert-liberatore is mentioning in the comments, the behaviour I'm describing is true for objects. Whenever your methods expect any object, you can assume that the JVM internally will make a copy of the reference to the object and pass it to your method. That's why having code like
void doSomething(List<Integer> x) {
x = new ArrayList<Integer>()
}
List<Integer> x = Arrays.asList(1, 2, 3);
doSomething(x);
x.length() == 3
behaves like it does. You're copying the reference to the list, so "reassigning it" will take no effect in the real object. But since you're referring to the same object, modifying its inner content will affect the outer object.
This is something you may miss when defining your attributes as final in order to achieve immutability. You won't be able to reassign them, but there's nothing preventing you from changing its content
Of course, this is true for objects where you have a reference. In case of primitives, which are not a reference to an object containing something but "something" themselves, the thing is different. Java will still make a copy of the whole value (as it does with the whole reference) and pass it to the method. But primitives are just values, you can't "modify its inner values". So any change inside a method will not have effect in the outer values
Now, talking about Kotlin
In Kotlin you "don't have" primitive values. But you "do have" primitive classes. Internally, the compiler will try to use JVM primitive values where needed but you can assume that you always work with the boxed version of the JVM primitives. Because of that, when possible the compiler will just make a copy of the primitive value and, in other scenarios, it will copy the reference to the object. Or with code
fun aJvmPrimitiveWillBeUsedHere(x: Int): Int = x * 2
fun aJvmObjectWillBeUsedHere(x: Int?): Int = if (x != null) x * 2 else 1
I'd say that Kotlin scenario is a bit safer than Java because it forces its arguments to be final. So you can modify its inner content but not reassign it
fun doSomething(x: MutableList<Int>) {
x.add(2) // this works, you can modify the inner state
x = mutableListOf(1, 2) // this doesn't work, you can't reassign an argument
}
It uses the same principles like Java. It is always pass-by-value, you can imagine that a copy is passed. For primitive types, e.g. Int this is obvious, the value of such an argument will be passed into a function and the outer variable will not be modified. Please note that parameters in Kotlin cannot be reassigned since they act like vals:
fun takeInt(a: Int) {
a = 5
}
This code will not compile because a cannot be reassigned.
For objects it's a bit more difficult but it's also call-by-value. If you call a function with an object, a copy of its reference is passed into that function:
data class SomeObj(var x: Int = 0)
fun takeObject(o: SomeObj) {
o.x = 1
}
fun main(args: Array<String>) {
val obj = SomeObj()
takeObject(obj)
println("obj after call: $obj") // SomeObj(x=1)
}
You can use a reference passed into a function to change the actual object.
The semantics is identical to Java.
In Java, when you have an instance of an object, and you pass it to a method, that method can change the state of that object, and when the method is done, the changes would have been applied to the object at the call site.
The same applies in Kotlin.
For primitives value is passed, and for non-primitives a reference to the object is passed. I'll explain with an example:
The code:
fun main() {
var a = 5
var b = a
a = 6
println("b = $b")
}
prints: b = 5
Kotlin passes the value of a to b, because a is a primitive. So changing a afterwards won't impact b.
The code:
fun main() {
var a = Dog(5)
var b = a
a.value = 6
println("b = ${b.value}")
}
class Dog (var value: Int)
prints b = 6, because this time a is not a primitive and so the reference to the object (Dog) was passed to b and not its value. Therefore changing a would affect all objects that point to it.
In Java primitive types like int, float, double, boolean are passed to a method by value, if you modify them inside the receiver method they doesn't change into the calling method. But if the property/variable type isn't a primitive, like arrays of primitives or other classes when they are changed inside the method that receive them as parameter they also change in the caller method.
But with Kotlin nothing seems to be primitive, so I think all is passed by reference.
This might be a little bit confusing.
The correct answer, IMHO, is that everything passes by reference, but no assignment is possible so it will be similar to passing by value in C++.
Note that function parameters are constant, i.e., they cannot be assigned.
Remember that in Kotlin there are no primitive types. Everything is an object.
When you write:
var x: Int = 3
x += 10
You actually create an object of type Int, assign it the value 3, and get a reference, or pointer, named x.
When you write
x += 10
You reassign a new Int object, with the value 13, to x. The older object becomes a garbage (and garbage-collected).
Of course, the compiler optimizes it, and creates no objects in the heap in this particular case, but conceptually it is as explained.
So what is the meaning of passing by reference function parameters?
Since no assignment is possible for function parameters, the main advantage of passing by reference in C++ does not exist in Kotlin.
If the object (passed to the function) has a method which changes its internal state, it will affect the original object.
No such method exists for Int, String, etc. They are immutable objects.
No copy is ever generated when passing objects to functions.
Bear in mind, am quite new to Kotlin. In my opinion, primitives are passed-by-value, but objects are passed-by-reference.
A primitive passed to a class works by default, but if you pass an object from a list, for example, and that object changes, the class object changes too. Because, in fact, it is the same object.
Additionally, if objects gets removed from the list, the class object IS STILL A REFERENCE. So it can still change due to references in other places.
Example below explaines. You can run it here.
fun main() {
val listObjects = mutableListOf(ClassB(), ClassB(), ClassB())
val listPrimitives = mutableListOf(111, 222, 333)
val test = ClassA()
test.ownedObject = listObjects[0]
test.ownedPrimitive = listPrimitives[0]
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listObjects[0].isEnabled = true
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listPrimitives[0] = 999
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
}
class ClassA {
var ownedObject: ClassB = ClassB()
var ownedPrimitive: Int = 0
}
class ClassB {
var isEnabled = false
}
Since Kotlin is a new language for JVM, like Java it is pass-by-value. The confusing part is with object, at first it looks like that it is passed-by-reference but the actuality is that the reference/pointer itself is pass-by-value (a copy of a reference is passed to a method) hence when a method receives a reference to an object, the method can manipulate the original object.

how to use MonoType in context of evaluating method signatures

I want to be able to call methods on CLR classes from C++. In particular some classes may contain overloaded methods, so I need to search a class's methods based both on method name and parameter signature.
I have a function like this:
MonoMethod* find_method (
MonoDomain* domain,
MonoClass* type,
const char* name,
int nargs,
MonoClass** types)
I iterate over the members of the class, finding a matching member by name. I then need to check the parameters of the method and see whether they match the list required in the types parameter of this function.
mono_signature_get_params() is then used to iterate over the parameters for each method with a matching name.
Questions:
How can I do the following:
access the MonoClass and MonoType struct fields
attempting to access fields in these structs results in error, as incomplete structs
compare a list of method parameters with another list provided as input to the function
cannot compare by enum as cannot access the enum field (see above)
get MonoClass* constants for fundamental types int32_class, int64_class, etc.
want to be able to easily compose a signature array using primitive type class constants
Here are 2 auxilliary functions that do not compile as when accessing fields in MonoType* or MonoClass*, the compiler complains indicating the two structures are incomplete:
//
// Detetermine whether classes A and B are equivalent
//
static bool IsEquivalent (MonoType* typeA, MonoType* typeB)
{
MonoTypeEnum Ta = typeA->type;
MonoTypeEnum Tb = typeB->type;
// if basic type not a match, can punt
if (Ta != Tb)
return false;
// if simple type, nothing further to check
if (Ta < MONO_TYPE_PTR)
return true;
// check class
if (Ta == MONO_TYPE_CLASS)
return typeA->data.klass = typeB->data.klass;
else
return typeA->data.klass = typeB->data.klass;
}
//
// Determine whether parameters in signature match incoming parameters
//
static bool types_match (
MonoMethodSignature* sig,
MonoClass** types,
int nargs)
{
void* iter = NULL;
MonoType* type = NULL;
int i = 0;
while (type = mono_signature_get_params (sig, &iter))
{
if (!IsEquivalent (type, types[i++]->this_arg))
return false;
}
return true;
}
You must not include the private mono headers: your app will break when we make changes to the internals.
To access the type enum value from a MonoType* you need to call the mono_type_get_type () function (from metadata/metadata.h). For MONO_TYPE_CLASS and MONO_TYPE_VALUETYPE you can access the MonoClass* value with mono_type_get_class ().
To compare two signatures for equality you can use mono_metadata_signature_equal(): note that using MonoClass* to represent an argument's type is fundamentally incorrect, since that can't represent, for example, an argument passed by reference.
If you need to match by assignability, you can use mono_class_is_assignable_from(), but note that you will need to deal with byref arguments, decide if you want to allow enum types to autoconvert to their underlying integer type etc.
The fundamental type classes can be trivially retrieved with functions like:
mono_get_int32_class(), mono_get_boolean_class() etc.