feat: core.async Phase 3 — channel transducers + dropping/sliding buffers

(chan n xform) applies a transducer on the put side: a jolt transducer is a
directly-callable closure, composed over a reducing fn whose step gives each
output value into the channel (honoring its buffer kind). One put may yield zero
or more values; a reduced result (e.g. from take) closes the channel; close!
runs the transducer completion arity to flush stateful remainders. Works with
map/filter/mapcat/take/comp/etc.

Buffers: (buffer n) fixed, (dropping-buffer n) drops new values when full,
(sliding-buffer n) drops the oldest. Implemented via a non-blocking give —
(ev/select [ch v] closed-chan) detects a full buffer without parking.

harness: run-spec flushes per suite. spec: core.async/channel-transducers (5),
core.async/buffers (3). jpm test green.

Note: distinct/dedupe/partition-all/partition-by still lack a 0-coll transducer
arity in core (separate gap), so they can't yet be used as channel xforms.
This commit is contained in:
Yogthos 2026-06-05 15:40:24 -04:00
parent e8cb4605ac
commit 54db79e927
5 changed files with 94 additions and 9 deletions

View file

@ -5,7 +5,7 @@
{"_type":"issue","id":"jolt-x8s","title":"CRITICAL: collections not callable as IFn (vector/map/set)","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:14Z","created_by":"Yogthos","updated_at":"2026-06-04T17:50:54Z","closed_at":"2026-06-04T17:50:54Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-alz","title":"CRITICAL: self-referential lazy-seq/lazy-cat yields only literal prefix","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:13Z","created_by":"Yogthos","updated_at":"2026-06-04T18:09:15Z","closed_at":"2026-06-04T18:09:15Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-wec","title":"CRITICAL: multi-collection map returns unrealized thunk","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:12Z","created_by":"Yogthos","updated_at":"2026-06-04T18:06:02Z","closed_at":"2026-06-04T18:06:02Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-5i5","title":"core.async Phase 2: dynamic var binding conveyance","description":"Snapshot/restore the global binding-stack per fiber so dynamic var bindings don't interleave across concurrent go blocks (Clojure binding conveyance).","status":"open","priority":2,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-05T18:55:08Z","created_by":"Yogthos","updated_at":"2026-06-05T18:55:08Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-5i5","title":"core.async Phase 2: dynamic var binding conveyance","description":"Snapshot/restore the global binding-stack per fiber so dynamic var bindings don't interleave across concurrent go blocks (Clojure binding conveyance).","status":"closed","priority":2,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-05T18:55:08Z","created_by":"Yogthos","updated_at":"2026-06-05T19:22:50Z","closed_at":"2026-06-05T19:22:50Z","close_reason":"Binding stack moved to fiber-local dyn; go-spawn snapshots+installs for conveyance; concurrent isolation + inner shadowing verified (4 spec cases)","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-tkw","title":"core.async on Janet fibers — Phase 1: API layer","description":"Implement clojure.core.async API (chan/go/\u003c!/\u003e!/\u003c!!/\u003e!!/close!/alts!/timeout/put!/take!/buffers) on top of Janet ev/ channels and fibers. go = run body in a fiber (stackful, no CPS macro needed).","status":"closed","priority":2,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-05T18:55:07Z","created_by":"Yogthos","updated_at":"2026-06-05T19:17:25Z","closed_at":"2026-06-05T19:17:25Z","close_reason":"Phase 1 complete: chan/go/\u003c!/\u003e!/close!/alts!/timeout/put!/take! on Janet fibers; two-channel design (values + done) gives drain-then-nil with no leaked fibers; 16 spec cases","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-lko","title":"clojure-test-suite: strictness — throw on malformed calls like Clojure","description":"Make jolt throw where Clojure throws (bad-shape conj!/assoc!, arithmetic on non-numbers, out-of-range indices, etc.) to satisfy the suite's ~292 p/thrown? assertions. Targeted input validation across affected fns; guard against regressing jolt's spec/conformance.","status":"closed","priority":2,"issue_type":"task","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-06-05T14:45:20Z","created_by":"Yogthos","updated_at":"2026-06-05T18:07:56Z","started_at":"2026-06-05T14:45:39Z","closed_at":"2026-06-05T18:07:56Z","close_reason":"Implemented Clojure-strict argument validation across ~30 fns; suite pass 3691-\u003e3898, p/thrown? bucket 292-\u003e~60 (remainder is platform: int 32-bit range, subs Unicode, min-key NaN, subvec floats, map-entry-as-2-vector)","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-kxb","title":"clojure-test-suite: transducers don't short-circuit over infinite seqs (hangs)","description":"(into [] (take 5) (range)) and similar transducer-over-infinite forms hang jolt's eager evaluator (no reduced/early-termination). 7 suite files time out. Make transducing honor reduced.","status":"closed","priority":2,"issue_type":"bug","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-06-05T13:05:18Z","created_by":"Yogthos","updated_at":"2026-06-05T13:18:37Z","started_at":"2026-06-05T13:09:59Z","closed_at":"2026-06-05T13:18:37Z","close_reason":"reduce-with-reduced steps lazy seqs incrementally; transducers short-circuit over infinite seqs","dependency_count":0,"dependent_count":0,"comment_count":0}