Clojure CLI 1.12.2.1571 is now available
โข https://clojure.atlassian.net/browse/TDEPS-272 clj -X:deps prep now supports prep of named tools via :tool
https://github.com/borkdude/deps.clj/releases/tag/v1.12.2.1571
Introducing https://github.com/anjensan/knitty - a small DAG-driven engine for async computations. Associate computations with keywords, define dependencies, provide values for initial nodes and then yank the values you need. It builds a DAG, checks for cycles, resolves (awaits) deferreds, memoizes results, and optionally offers tracing/profiling. Prod-proven for 1+ year.
I've build something like that in Java 18 years ago. It would parse systems of equations from C++ (50k+ equations) into a DAG and calculate time series models for macroeconomic predictions. Values were only calculated once each iteration but it wasn't asynchronous. It was a cool piece of software, a generic calculation engine. But with Clojure it would have been much easier.
Nice. This remind me of the graph lib in https://github.com/plumatic/plumbing?tab=readme-ov-file#graph-the-functional-swiss-army-knife : a declarative way to specify a structured computation.
@kawas good catch. They mentioned that here https://github.com/anjensan/knitty/blob/master/doc/rationale.md
Yes! It is quite similar to plumatic.plumbing. Also I like to mention com.troy-west/wire (similar) and io.github.bortexz/graphcom (focused on reexecuting graph, nodes recieve their previous state). I did some experimenting with plumatic.plumbing - it looks really nice! Also very optimized, overhead is extremely low, much better than knitty. But it just did not fit to the requirements - no conditional deps and no deferreds. In the project knitty come from there are ~300 nodes, so not so manageable without namespaces. A lot of conditionals (aka ^:lazy). Also there is dynamic rendering, where a "template" (semi-dynamic, comes from db, contains placeholders) rendered based on values from nodes. With knitty only used nodes are rendered (that was main motivation to include ^:case bindings in the first place). Plus tracing is a neat feature - based on conditions (dynamic) some requests was rendered with tracing and their results/trace is available via dedicated debugging webpage.
So cool, at my previous job we built a lib called Laplace, for python though, that did the exact same thing. The lib was used for stock based compensation accounting reports -- there were close to 200 variables calculated for every tranche of every equity award.
Kind of reminds me of how Kafka Streams computes a topology for its worker threads.