# Platform Notes

> USearch for Java

### Kotlin & Scala

The published surface is Java, and both other JVM languages consume it directly, so there is no separate artifact for either.

Nullness is part of the contract.
The package is `@NullMarked`, so a Kotlin caller gets real non-null types across the whole boundary rather than platform types, and the compiler refuses a null where the API does not accept one.
`AutoCloseable` is Kotlin's `use`, and a coroutine waits on a `Deferred` with `withContext(Dispatchers.IO)`:

```kotlin
val index: DenseIndex = DenseIndex.initRam(DenseOptions().dimensions(2).quantization(Scalar.BF16), intArrayOf())
index.use {
Arena(pool).use { arena ->
    val matches = withContext(Dispatchers.IO) { index.deferred(pool).search(queries, 10, arena).use { it.join() } }
    println(matches.key(0, 0))          // valid until the next call given `arena`, or its close
}
}
```

Scala reads no nullness annotations, so what it gets instead is that the array-based batch verbs take `Array[Key]` and `Array[Float]` with no conversion, since both are JVM arrays already:

```scala
val keys: Array[Key] = Array(Key.of(1), Key.of(2))
index.on(pool).insert(keys, RowsView.of(Array(1.0f, 0.0f, 0.0f, 1.0f), 2))
```

### What This Binding Does Not Expose

The filtered search of the C interface stays unbound.
Its predicate runs on the engine's own worker threads, which are not attached to the JVM, so every batch of candidates would pay an attach, an upcall, and an exception check.
A predicate that threw would also unwind through native frames that cannot handle it.
Filter the results of `search` instead, or narrow the index.
Progress handlers stay unbound for the same reason, which is what makes an insertion batch all-or-nothing here.

`cursor` and `searchStream` pull one batch at a time, blocking, so a `DeferredOn` lacks them, and constructors address no index yet, so no receiver offers them.

### Design

- __A thin layer over the C ABI.__
  Every name follows `include/usearch/`: a C verb `usearch_dense_<verb>` is a camel-cased `<verb>` here, a C type drops `usearch_` and `_t`, and enums mirror C enums, never strings.
  Every wrapper's documentation names the C symbol it calls, or says it is binding-only.
- __The receiver chooses, the verb stays.__
  The index runs a verb on the calling thread, `on(executor)` blocks on an executor, and `deferred(executor)` submits it, all with the same arguments.
- __Deferred calls use the language's own idioms.__
  `status` polls through `usearch_outcome_status`, `join` blocks through `usearch_outcome_wait`, and a `Deferred` is `AutoCloseable`, so Java waits in try-with-resources or on a virtual thread, and Kotlin in `withContext(Dispatchers.IO)`.
- __No life of its own.__
  The binding starts no threads and keeps no queues; releasing a `Deferred` rides try-with-resources, whose `close` waits for the call first, and the collector frees a dropped one only once it is final.
- __Arenas are lent and reused, never shared.__
  Every output whose length scales with the call lands in an arena the caller passes; each call closes the FFM scope the previous call's views read through, so a stale view throws instead of reading reused memory.
- __Nothing costs anything until it is used.__
  Submitting a call allocates nothing, and an arena allocates only when a call writes into it.
- __Blocking calls stay as simple as the language allows.__
  `index.search(queries, 10, arena)` takes no executor, completion or callback and returns its result; nothing about asynchrony reaches a caller who never asks for it.
- __Argument structures live in FFM arenas.__
  A blocking call fills its C argument structure in a confined arena freed on return and takes no lock; a deferred one keeps it in a shared arena until the call is final.

