eve/obj provides schema-based typed objects backed by SharedArrayBuffer. Two representations are available, optimized for different access patterns:
eve-obj(AoS — Array of Structures): A single object with named typed fields. Good for individual records, tree nodes, and whole-object operations.eve-obj-array(SoA — Structure of Arrays): A collection of objects stored column-wise. Good for batch processing, SIMD operations, and cache-efficient iteration.
Both provide full Atomics API for cross-worker access.
Important: Like all EVE types, typed objects must be used within atoms. They are allocated from the global AtomDomain's shared memory and should be created and manipulated inside swap!, reset!, or atom construction.
(ns my-app.core
(:require [eve.alpha :as e]
[eve.obj :as obj]))A schema defines the shape of an object — like a V8 hidden class. Create once, reuse for many objects:
(def node-schema
(obj/create-schema {:key :int32
:left :int32
:right :int32
:value :float64}))| Type | Size | Atomic? | Description |
|---|---|---|---|
:int8 |
1B | No | Signed 8-bit integer |
:uint8 |
1B | No | Unsigned 8-bit integer |
:int16 |
2B | No | Signed 16-bit integer |
:uint16 |
2B | No | Unsigned 16-bit integer |
:int32 |
4B | Yes | Signed 32-bit integer (Atomics.load/store) |
:uint32 |
4B | Yes | Unsigned 32-bit integer (Atomics.load/store) |
:float32 |
4B | No | 32-bit float |
:float64 |
8B | No | 64-bit float |
:obj |
4B | Yes | Offset reference to another eve-obj |
:array |
4B | Yes | Offset reference to an eve-array |
Fields are sorted by alignment (descending) for optimal memory packing.
Create and store typed objects inside atom transactions:
(defonce state (e/atom {:tree nil}))
;; Create a node inside a swap!
(swap! state assoc :tree
(obj/obj node-schema {:key 42 :left -1 :right -1 :value 3.14}))Eve objects implement ILookup, IFn, and ISeqable. Inside a transaction:
(swap! state
(fn [s]
(let [node (:tree s)]
(println (:key node)) ;=> 42
(println (:value node)) ;=> 3.14
(println (node :key)) ;=> 42
(println (count node)) ;=> 4
(println (seq node))) ;=> ([:key 42] [:value 3.14] [:left -1] [:right -1])
s))Mutation operations should be done within atom transactions or when you have exclusive access:
(swap! state update :tree
(fn [node]
(obj/assoc! node :key 100)
node))
;; Atomic operations on int32/uint32 fields:
;; obj/cas! — compare-and-swap, returns true if swapped
;; obj/add! — atomic add, returns old value
;; obj/sub! — atomic subtract, returns old value
;; obj/exchange! — atomic exchange, returns old valueIf you don't need to reuse the schema, pass the field map directly:
(swap! state assoc :point
(obj/obj {:x :float64 :y :float64} {:x 1.5 :y 2.5}))For batch processing, obj-array stores N objects as separate column arrays — one typed array per field. This is cache-efficient and SIMD-friendly:
(defonce particles (e/atom {:data nil}))
;; Create an array of 1000 nodes inside a swap!
(swap! particles assoc :data
(obj/obj-array 1000 {:x :int32 :y :int32 :velocity :int32}))(swap! particles
(fn [s]
(let [data (:data s)]
;; Set field at [index, field-key]
(obj/assoc-in! data [0 :x] 42)
(obj/assoc-in! data [0 :y] 100)
;; Get field at [index, field-key]
(println (obj/get-in data [0 :x])) ;=> 42
;; Row view — object-like access to a single row
(println (nth data 0)) ;=> #eve/obj-array-row {:x 42, :y 100, :velocity 0}
(println (:x (nth data 0)))) ;=> 42
s))(swap! particles
(fn [s]
(let [data (:data s)]
;; Get the raw Int32Array for a field — use for SIMD or bulk operations
(let [x-col (obj/column data :x)]
;; use x-col for SIMD operations
)
;; Reduce over a single column
(obj/column-reduce data :x 0
(fn [acc idx val] (+ acc val)))
;; Map in-place over a column
(obj/column-map! data :x
(fn [idx val] (* val 2))))
s))Most application state should use regular Clojure maps — they're automatically stored as EVE hash-maps inside shared atoms. Use eve/obj when you need:
- Typed numeric fields with atomic operations (CAS, add, sub)
- SoA layout for SIMD-friendly batch processing
- Fine-grained field-level atomics across workers
- Memory-efficient storage for large numbers of uniform records