Kotlin/Native how to create Array of CPointers? - kotlin

I'm new to Kotlin/Native! I'd like to create an array of CPointers to pass it around, but having hard time creating one.
In C/C++ void* a[] = {test} is enough. But I'm not able to do the same in K/N.
I've tried val a: CValuesRef<out COpaquePointerVar> = cValuesOf(test)
But it results in the following error:
Tried looking at docs and find it on the web, but none of them answered correctly.
Any help is appreciated!!

So I basically did what I wanted using a StableRef
on_exit(staticCFunction { _, argsPtr ->
val argsStableRef = argsPtr!!.asStableRef<List<COpaquePointer>>()
val args = argsStableRef.get()
// Cleanup code
argsStableRef.dispose()
}, StableRef.create(listOf(/* All the pointers */)).asCPointer())
Basically transforming the List<COpaquePointer> to a StableRef and extracting pointer out of it, then when required deref it via the asStableRef and after that dispose it to ensure memory have been freed.

Related

Why does Kotlin's compiler not realize when a variable is initialized in an if statement?

The following example of Kotlin source code returns an error when compiled:
fun main() {
var index: Int // create an integer used to call an index of an array
val myArray = Array(5) {i -> i + 1} // create an array to call from
val condition = true // makes an if statement run true later
if (condition) {
index = 2 // sets index to 2
}
println( myArray[index] ) // should print 2; errors
}
The error says that the example did not initialize the variable index by the time it is called, even though it is guaranteed to initialize within the if statement. I understand that this problem is easily solved by initializing index to anything before the if statement, but why does the compiler not initialize it? I also understand that Kotlin is still in beta; is this a bug, or is it intentional? Finally, I am using Replit as an online IDE; is there a chance that the compiler on the website simply is an outdated compiler?
The compiler checks whether there is a path in your code that the index may not be initialized based on all the path available in your code apart from the value of the parameters. You have an if statement without any else. If you add the else statement you will not get any compile error.

Async Wait Efficient Execution

I need to iterate 100's of ids in parallel and collect the result in list. I am trying to do it in following way
val context = newFixedThreadPoolContext(5, "custom pool")
val list = mutableListOf<String>()
ids.map {
val result:Deferred<String> = async(context) {
getResult(it)
}
//list.add(result.await()
}.mapNotNull(result -> list.add(result.await())
I am getting error at
mapNotNull(result -> list.add(result.await())
as await method is not available. Why await is not applicable at this place? Instead commented line
//list.add(result.await()
is working fine.
What is the best way to run this block in parallel using coroutine with custom thread pool?
Generally, you go in the right direction: you need to create a list of Deferred and then await() on them.
If this is exactly the code you are using then you did not return anything from your first map { } block, so you don't get a List<Deferred> as you expect, but List<Unit> (list of nothing). Just remove val result:Deferred<String> = - this way you won't assign result to a variable, but return it from the lambda. Also, there are two syntactic errors in the last line: you used () instead of {} and there is a missing closing parenthesis.
After these changes I believe your code will work, but still, it is pretty weird. You seem to mix two distinct approaches to transform a collection into another. One is using higher-order functions like map() and another is using a loop and adding to a list. You use both of them at the same time. I think the following code should do exactly what you need (thanks #Joffrey for improving it):
val list = ids.map {
async(context) {
getResult(it)
}
}.awaitAll().filterNotNull()

How do I add multiple copies of the same String to an existing ArrayList?

I have an ArrayList<String>. I want to add n copies of a new String to it.
I've Googled generally and searched on StackOverflow. I've looked at the documentation.
Surely there's a better way than doing a loop?
I was hoping for something like:
myArray.addAll (ArrayList<String>(count: 10, value: "123"))
You can initialize a List with a given size n and an initializer function like this:
fun main() {
val n = 10
val defaultList = List(n) { it -> "default" } // you can leave "it ->" here
println(defaultList)
}
This piece of code then outputs
[default, default, default, default, default, default, default, default, default, default]
If you want to intialize an Array<String> directly without using a List as intermediate, you can do
val defaultArray: Array<String> = Array(n) { "default" }
println(defaultArray.contentToString())
in the main and get the same output (even without the it ->, which, indeed, isn't necessary in this case).

With Arrow: How do I apply a transformation of type (X)->IO<Y> to data of type Sequence<X> to get IO<Sequence<Y>>?

I am learning functional programming using Arrow.kt, intending to walk a path hierarchy and hash every file (and do some other stuff). Forcing myself to use functional concepts as much as possible.
Assume I have a data class CustomHash(...) already defined in code. It will be referenced below.
First I need to build a sequence of files by walking the path. This is an impure/effectful function, so it should be marked as such with the IO monad:
fun getFiles(rootPath: File): IO<Sequence<File>> = IO {
rootPath.walk() // This function is of type (File)->Sequence<File>
}
I need to read the file. Again, impure, so this is marked with IO
fun getRelevantFileContent(file: File): IO<Array<Byte>> {
// Assume some code here to extract only certain data relevant for my hash
}
Then I have a function to compute a hash. If it takes a byte array, then it's totally pure. Making it suspend because it will be slow to execute:
suspend fun computeHash(data: Array<Byte>): CustomHash {
// code to compute the hash
}
My issue is how to chain this all together in a functional manner.
fun main(rootPath: File) {
val x = getFiles(rootPath) // IO<Sequence<File>>
.map { seq -> // seq is of type Sequence<File>
seq.map { getRelevantFileContent(it) } // This produces Sequence<IO<Hash>>
}
}
}
Right now, if I try this, x is of type IO<Sequence<IO<Hash>>>. It is clear to me why this is the case.
Is there some way of turning Sequence<IO<Any>> into IO<Sequence<Any>>? Which I suppose is essentially, probably getting the terms imprecise, taking blocks of code that execute in their own coroutines and running the blocks of code all on the same coroutine instead?
If Sequence weren't there, I know IO<IO<Hash>> could have been IO<Hash> by using a flatMap in there, but Sequence of course doesn't have that flattening of IO capabilities.
Arrow's documentation has a lot of "TODO" sections and jumps very fast into documentation that presumes a lot of intermediate/advanced functional programming knowledge. It hasn't really been helpful for this problem.
First you need to convert the Sequence to SequenceK then you can use the sequence function to do that.
import arrow.fx.*
import arrow.core.*
import arrow.fx.extensions.io.applicative.applicative
val sequenceOfIOs: Sequence<IO<Any>> = TODO()
val ioOfSequence: IO<Sequence<Any>> = sequenceOfIOs.k()
.sequence(IO.applicative())
.fix()

Kotlin and parallelStream toArray

I think I'm getting sidetracked. I'm trying to utilize the Java parallelStream for performance reasons.
A function Specimen.pick() samples and returns an instance of Specimen.
I want to parallize this with parallelStream when replacing pool.
var pool: Array<Specimen> = Array(100_000) ..
This is what I'm trying to write in Kotlin:
pool = pool.asList().parallelStream().map { Specimen.pick(pool, wheel, r.split()) }.toArray(Specimen::new)
Which errors out on ::new
Instead I have to juggle back and forth between list and array:
pool = pool.asList().parallelStream().map { Specimen.pick(pool, wheel, r.split()) }.collect(Collectors.toList()).toTypedArray()
Which works, but seems resource wasteful rather than going directly to Array. If I let IntelliJ try to Kotlinize a Java example of this:
Java:
Person[] men = people.stream()
.filter(p -> p.getGender() == MALE)
.toArray(Person[]::new);
IntelliJ transformation:
val men = people.stream()
.filter({ p -> p.getGender() === MALE })
.toArray(Person[]::new /* Currently unsupported in Kotlin */)
So maybe this is coming for Kotlin? Or is there another better way?
You can't use an array constructor reference, but every method reference can be expressed using a lambda expression:
.toArray<Person>({length -> arrayOfNulls(length)})