datahike

whilo 2026-05-19T04:15:14.309429Z

A friendly reminder that I will give a talk at London Clojurians tomorrow https://www.meetup.com/london-clojurians/events/314510668/

🔥 4
whilo 2026-05-19T11:33:50.126209Z

Announcing Spindel — Reactive Computation You Can Fork We're releasing Spindel, a reactive programming system for Clojure/ClojureScript where the execution context — every signal, every cached spin result, every continuation — is a first-class forkable value. Key Features:O(1) forking — copy-on-write overlay backends; fork the reactive system, mutate independently, snapshot, serialize • Typed delta algebra — sequence / map / scalar algebras flow inline; O(delta) updates from signal mutation to DOM patch • Pluggable effectsspin macro is a CPS transform; libraries register their own breakpoint symbols (probabilistic programming, distributed RPC, …) • Cross-platform.cljc everywhere; same semantics on JVM and ClojureScript

(require '[org.replikativ.spindel.core :as s :refer [spin signal track]]
         '[org.replikativ.spindel.incremental.interval :as iv]
         '[org.replikativ.spindel.engine.impl.simple :as engine])

(def root (s/create-execution-context))
(s/with-context root
  (def counter (signal 0))
  (def doubled (spin (* 2 (iv/get-new (track counter))))))

;; Fork the entire reactive system
(def fork (s/fork-context root))

(s/with-context fork
  (swap! counter inc)
  (engine/await-drain-complete! fork)
  @doubled)        ; => 2 (fork has its own counter)

(s/with-context root
  @doubled)        ; => 0 (parent untouched)
Install: org.replikativ/spindel {:mvn/version "0.1.5"} Links: • GitHub: https://github.com/replikativ/spindel • Examples: https://github.com/replikativ/spindel/tree/main/examples • Engine deep-dive: https://github.com/replikativ/spindel/blob/main/docs/engine.md Feedback appreciated!

👏 5
🔥 1
2026-05-23T15:38:47.603629Z

just a light doc note, I was getting confused by my own repl results of https://github.com/replikativ/spindel/blob/main/docs/getting-started.md#signal-updates-drive-re-execution of the getting started page until i re-read the readme example and realized i needed engine/await-drain-complete! to block and get deterministic results. (without it, the deref result/overall return value wasn't always reflecting the swap! result just before it in the same binding block for me)

whilo 2026-05-23T18:13:17.185949Z

Thanks @jjttjj, yes this is misleading.

whilo 2026-05-22T20:26:14.262329Z

Thank you @chromalchemy!

whilo 2026-05-22T20:26:29.324659Z

Landed some fixes to spindel and tried to pin down the engine semantics to make it clearer to reason about https://github.com/replikativ/spindel/blob/main/docs/engine-formalism.md. Feedback welcome, in particular about things that are unclear.

chromalchemy 2026-05-20T14:06:13.521049Z

Shared some of your context with @hiskennyness here https://clojurians.slack.com/archives/CKCBP3QF9/p1779222620281339

2026-05-19T14:38:10.500389Z

Looks really cool! Just a heads up, it's possible I'm doing something wrong, but I was trying to run the examples and they all worked for me except the versioned-editor-demo. I was able to get it working by adding the shared.js lib and initializing the example in the html file (which the other examples seem to all do). here is the patch that worked for me:

modified   examples/public/versioned-editor-demo.html
@@ -591,6 +591,8 @@
     Prototype for simmis branching UX.
   </footer>

+  <script src="/js/shared.js"></script>
   <script src="/js/versioned-editor-demo.js"></script>
+  <script>examples.versioned_editor_demo.init();</script>
 </body>
 </html>
(probably should have dom ready checks like the others do)

whilo 2026-05-19T16:11:40.679819Z

Yes, good catch, ran into this, too 🙂 .

👍 1
2026-05-28T12:00:18.102949Z

Very cool, but is there any straightforward ability to create spins dynamically in runtime? Like I understand spin macro implements spins on compile time...

2026-05-28T13:47:02.094769Z

I see in API functions like (spin-register! spin-id meta) but, if it is intended to be dynamically assigned, please tell best-practices about it

whilo 2026-05-28T16:55:29.815059Z

you can call make-spin directly, i will take a look

whilo 2026-05-28T19:04:35.209259Z

Can you be more specific with what you mean by dynamic? There are already three ways, depending on what you're after: 1. Composing spins from runtime data (most common): build leaf spins with the spin macro and combine them with parallel/`race` using runtime values — the number, ordering and wiring of spins is fully dynamic. The only rule is that await/`track` must appear lexically inside some (spin …) form (same constraint as core.async's go). E.g. (let [children (map #(spin (await (fetch %))) items)] (spin (await (apply parallel children)))). 2. Calling make-spin directly: you can hand it a (fn [resolve reject] …), exactly like the built-in combinators do (see sleep in spin/combinators.cljc). Perfect for wrapping an external promise/callback/deferred at runtime. Caveat: await/`track` are compile-time breakpoints, so they don't work inside a fn you construct at runtime — you write the continuation by hand here (`(resolve v)` / incomplete). 3. Truly dynamic bodies that still use effects (code not known at compile time, with await/`track` inside): use the SCI integration (`sci/boundary.clj`), which interprets the spin macro at runtime so the CPS transform happens on the fly. spin-register!/`spin-id` aren't the entry point for any of this — they're internal lifecycle/addressing bookkeeping that make-spin does for you. Which of the three are you reaching for?

2026-05-28T19:41:25.692459Z

Thank you for such comprehensive answer. I want to have some kind of spins repository (map i guess?) and put or remove spins from there with user's interactions. And need these spins to interact each other inside execution context. Looks like make-spin is the thing i am talking about. I'll try

2026-06-24T20:46:59.218229Z

Made with Spindel =) Announcing SaltRim - Clojure spreadsheets processor written with replikativ's Spindel and Datahike. https://saltrim.michelada.uno https://github.com/michelada-uno/saltrim Also one of points was to minimise client's code and do most of UI with SSE (Datastar).

whilo 2026-06-24T22:56:26.098499Z

@sasha_bogdanov_dev This is super cool! I will take a closer look later. Maybe this is helpful for you, too https://github.com/replikativ/rechentafel/

👍 1
2026-06-25T23:06:51.070119Z

Rechentafel is very nice but right now I do not see any availability to put in inside the saltrim code. Maybe later. I am open to suggestions and collaboration!