https://clojure.org/news/2023/10/06/deref Clojure logo Clojure OverviewReferenceAPIReleasesGuidesCommunityDevNews [ ] [clojure.org ] [Search] Clojure Deref (Oct 6, 2023) Clojure Deref (Sept 29, 2023) Clojure Deref (Sept 22, 2023) Clojure Deref (Sept 15, 2023) Clojure Deref (Sept 8, 2023) Clojure Deref (Sept 1, 2023) Clojure Deref (Aug 25, 2023) Clojure Deref (Aug 18, 2023) Clojure Deref (Aug 11, 2023) Clojure Deref (Aug 6, 2023) (next Rich) Clojure Deref (July 28, 2023) Clojure Deref (July 20, 2023) Clojure Deref (July 7, 2023) Clojure Deref (June 30, 2023) State of Clojure 2023 Results Clojure Deref (June 23, 2023) Clojure Deref (June 16, 2023) Clojure Deref (June 9, 2023) Clojure Deref (June 2, 2023) Clojure Deref (May 26, 2023) Clojure Deref (May 19, 2023) Clojure Deref (May 12, 2023) Clojure Deref (May 5, 2023) Clojure Deref (May 1, 2023) Introducing Morse Clojure Deref (Apr 21, 2023) Clojure Deref (Apr 14, 2023) Clojure 1.12.0-alpha2 Clojure Deref (Apr 10, 2023) Clojure Deref (Mar 31, 2023) Clojure Deref (Mar 27, 2023) Clojure Deref (Mar 18, 2023) Clojure Deref (Mar 10, 2023) Clojure Deref (Mar 3, 2023) State of Clojure 2023 Survey Clojure Deref (Feb 26, 2023) Clojure Deref (Feb 17, 2023) Clojure Deref (Feb 10, 2023) Clojure Deref (Feb 3, 2023) Clojure Deref (Jan 30, 2023) Clojure Deref (Jan 20, 2023) Clojure Deref (Jan 13, 2023) Clojure Deref (Jan 6, 2023) Clojure Deref (Dec 22, 2022) Clojure Deref (Dec 16, 2022) Clojure Deref (Dec 8, 2022) Clojure Deref (Dec 2, 2022) Clojure Deref (Nov 23, 2022) Clojure Deref (Nov 18, 2022) Clojure Deref (Nov 11, 2022) Clojure Deref (Nov 4, 2022) Clojure Deref (Oct 28, 2022) Clojure Deref (Oct 21, 2022) Clojure Deref (Oct 14, 2022) Clojure Deref (Oct 10, 2022) Clojure Deref (Oct 3, 2022) Clojure Deref (Sep 26, 2022) Clojure Deref (Sep 16, 2022) Clojure Deref (Sep 9, 2022) Clojure Deref (Sep 2, 2022) Clojure Deref (Aug 26, 2022) Clojure Deref (Aug 19, 2022) Clojure Deref (Aug 12, 2022) Clojure Deref (Aug 5, 2022) Clojure Deref (July 30, 2022) Clojure Deref (July 15, 2022) Clojure Deref (July 8, 2022) Clojure Deref (July 1, 2022) Clojure 1.12.0-alpha1 Clojure Deref (June 24, 2022) Clojure Deref (June 17, 2022) Clojure Deref (June 10, 2022) State of Clojure 2022 Results Clojure Deref (June 2, 2022) Clojure Deref (May 27, 2022) Clojure Deref (May 20, 2022) Clojure Deref (May 13, 2022) Clojure Deref (May 6, 2022) Clojure Deref (Apr 29, 2022) Clojure Deref (Apr 22, 2022) Clojure Deref (Apr 14, 2022) Clojure Deref (Apr 8, 2022) Clojure 1.11.1 release Clojure Deref (Apr 1, 2022) Clojure Deref (Mar 25, 2022) Clojure 1.11.0 release Clojure Deref (Mar 20, 2022) Clojure Deref (Mar 11, 2022) Clojure Deref (Mar 4, 2022) Clojure Deref (Feb 28, 2022) State of Clojure 2022 Survey Clojure Deref (Feb 18, 2022) Clojure Deref (Feb 14, 2022) Clojure Deref (Feb 4, 2022) Clojure Deref (Jan 28, 2022) Clojure Deref (Jan 21, 2022) Clojure Deref (Jan 14, 2022) Clojure Deref (Jan 7, 2022) Clojure Deref (Dec 23, 2021) Clojure Deref (Dec 17, 2021) Clojure Deref (Dec 10, 2021) Clojure Deref (Dec 2, 2021) Clojure Deref (Nov 24, 2021) Clojure Deref (Nov 19, 2021) Clojure Deref (Nov 12, 2021) Clojure Deref (Nov 5, 2021) Clojure Deref (Oct 29, 2021) Clojure Deref (Oct 22, 2021) Clojure Deref (Oct 14, 2021) Clojure Deref (Oct 8, 2021) Clojure Deref (Sept 24, 2021) Clojure Deref (Sept 17, 2021) Clojure Deref (Sept 10, 2021) Clojure Deref (Sept 3, 2021) Clojure Deref (Aug 27, 2021) Clojure Deref (Aug 20, 2021) Clojure Deref (Aug 13, 2021) Clojure Deref (July 30, 2021) Clojure Deref (July 23, 2021) Clojure Deref (July 16, 2021) Source Libs and Builds Clojure Deref (July 9, 2021) Clojure Deref (July 2, 2021) Clojure Deref (June 25, 2021) Clojure Deref (June 18, 2021) Clojure Deref (June 11, 2021) Clojure Deref (June 4, 2021) State of Clojure 2021 Results Keyword argument functions now also accept maps Clojure 1.10.3 release Clojure 1.10.2 release State of Clojure 2021 Survey Cognitect Joins Nubank! Clojure Homebrew Tap State of Clojure 2020 Results State of Clojure 2020 Survey Clojure Forum Clojure 1.10.1 release JIRA Migration State of Clojure 2019 Results State of Clojure 2019 Survey Clojure 1.10 release State of Clojure 2018 Results Git Deps for Clojure Clojure 1.9 is now available State of Clojure 2016 Results Introducing clojure.spec State of Clojure 2015 survey results Clojure 1.8 is now available Welcome to the new clojure.org! Clojure 1.7 is now available Transducers are Coming Clojure core.async Channels Anatomy of a Reducer Reducers - A Library and Model for Collection Processing Clojure Governance and How It Got That Way Introducing ClojureScript Clojure Deref (Oct 6, 2023) Clojure Deref (Oct 6, 2023) 06 October 2023 Alex Miller Welcome to the Clojure Deref! This is a weekly link/news roundup for the Clojure ecosystem (feed: RSS). Thanks to Anton Fonarev for link aggregation. From the core Recently Java 21 was released (congrats!) and this has driven a lot of interest and experimentation with the new virtual threads feature. Virtual threads have the ability to park and resume a virtual thread (particularly one blocked on I/O) and this cooperates transparently with many blocking constructs in Java - I/O, sockets, java.util.concurrent.lock, etc. However, one thing it does not (yet) cooperate with is object monitors (synchronized) and thus doing a blocking call while holding a synchronized monitor prevents a virtual thread from parking (ie, "pins" the virtual thread). Note that synchronization itself is not inherently bad - normal use of synchronized to serialize reads and writes to fields is fine (as there is no blocking I/O that can pin a thread). Several people doing new things with virtual threads have detected cases where user code is doing I/O blocking while Clojure is in a synchronization block, thus pinning threads. The two most important cases are lazy seqs and delay - both hold some suspended computation in a thunk and invoke the thunk under synchronization, thus allowing for the possibility of user I/O under a lock in the language level. As people have raised this as an issue, we have spent the last week taking a hard look at this area. At a meta level, there are a bunch of options here and we have still not decided on our approach or timeframe. From a user level, it is possible to simply not do (or tolerate) I/O under delay or lazy seqs. Delay is a one-time thing, so it may not generally be an issue to pin a thread that is reading a config file as that is a one-time thing. Pulling I/O over a lazy seq is not uncommon and can definitely present this kind of issue, but there are a lot of other options - controlling via loop/recur, using transducers and sequence, etc. If you are experiencing this problem now, these are probably worth exploring. We've spent a ton of time over the last week looking at the internals of LazySeq and options for avoiding synchronization. The general guidance from Java is to replace synchronized with ReentrantLock (which has virtual thread coordination), but this advice leaves out the inherent tradeoffs in that change. synchronized relies on object monitors which are built into every Java object at the JVM level, whereas ReentrantLocks are additional Java objects (which hold a reference to an internal Sync object). Clojure makes a lot of lazy seqs and allocating two objects (plus adding an additional field to LazySeq) for every lazy seq is a real cost in allocation, heap size, and GC. Additionally, while ReentrantLock seems to be a bit faster than synchronized in Java 21, LazySeq makes one reentrant call, and reentrant calls seems to be noticeably slower than synchronized. There are lots of options though. We think it's relatively easy to make lazy seq walking faster, but a lot harder to keep realization costs under control (as making locks takes non-zero time). One interesting branch we have explored is making one lock per seq and passing it through the seq as we go - lots of tradeoffs in that. Additionally, we continue to work on functional interface adapters and method thunks. With FI adapters, we continue to refine when implicit coercion and conversion occur and I think that draws asymptotically closer to completion. With method thunks, we have taken a bit of a detour to examine array class representation. Generally, classes are represented by symbols that name the class, but this does not work for array classes as they cannot be represented as a valid symbol. The fallback right now is using a String that holds the internal class name, like ^"[Ljava.lang.String; " which I think we can all agree is no fun. Our plan going forward is to support a new array class syntax which is a symbol of the class with a * suffix. Imported classes can use their short name, so String* will represent a Java String[] (or a String... vararg). Multiple ** will represent multidimensional arrays. This will work with both classes and with primitives, so long* will be a synonym for the existing longs. Rich also wishes you to notice the C pointer punnery. :) That was a bit of a diversion, but I think it is a big win to fix a long-time representational gap. It also helps create some new "columns" in the varargs decision matrix, which is not going to be addressed in 1.12, but I think we have teed up to work on immediately after. Podcasts and videos * #91 Josh Glover - defn * Ep 092: Freeing Limits - Functional Design in Clojure * Ep 093: Waffle Cakes - Functional Design in Clojure * Matrix Exposed! (or, You Don't Know Reactive) (by Kenny Tilton) - London Clojurians * Scicloj LLM Meetup 4: transformer-based generative LLMs - Sci Cloj * Scicloj LLM Meetup 5: Library overviews - Sci Cloj * Parens of the Dead - Episode 24: Merry Happy! - emacsrocks * Complete Clojure Development Environment Setup: IntelliJ IDEA, Cursive, ASDF/RTX, Toolbox - Andrey Fadeev * Private Methods in Clojure - Clojure Diary * Pedestal 7 - Cookies - Clojure Diary * Conhecendo Datomic - Joao Palharini - clojure-br Blogs, articles, and projects * Following our first five LLM meetups - Daniel Slutsky * Include interactive Clojure/script code snippets in a web page with SCI & friends - Jakub Holy * OSS updates September 2023 - Michiel Borkent * Lazy, Chunked, and Buffered: Understanding Clojure's Lazy Sequences - Bruno Bonacci Libraries and Tools New releases and tools this week: * fulcro-troubleshooting v7 - A development-time library for Fulcro that helps to detect problems earlier and find and fix their root cause faster * minimalist-fulcro-template-backendless - A minimal template for browser-only Fulcro apps for learning * clojure-test 2.1.182 - A clojure.test-compatible version of the classic Expectations testing library * clerk 0.15.957 - Moldable Live Programming for Clojure * deps-diff 1.1 - A tool for comparing transitive dependencies in two deps.edn files * datalevin 0.8.20 - A simple, fast and versatile Datalog database * antq 2.7.1133 - Point out your outdated dependencies * tab 2023-10-03.333 - A tool for tabulating Clojure collections * pp 2023-10-05.5 - Pretty-print Clojure data structures, fast * raphael 0.3.0 - A Clojure library for parsing strings containing the Terse Triples Language: Turtle * clj-otel 0.2.4.1 - An idiomatic Clojure API for adding telemetry to your libraries and applications using OpenTelemetry * neil 0.2.61 - A CLI to add common aliases and features to deps.edn-based projects * squint 0.2.30 - ClojureScript syntax to JavaScript compiler * Tutkain 0.19.0 (alpha) - A Sublime Text package for interactive Clojure development * cherry 0.1.9 - Experimental ClojureScript to ES6 module compiler * taplet 1.0.58 - A Clojure/ClojureScript macro, let> that works like a let, and also tap>s the binding vector * nbb 1.2.179 - Scripting in Clojure on Node.js using SCI Community Resources Contributing Companies Site Legal License Privacy Policy Documentation Overview Reference API Guides Libraries & Tools Updates News Events ETC ClojureTV Books Swag Code Releases Source ClojureScript ClojureCLR Copyright 2008-2022 Rich Hickey | Privacy Policy Logo & site design by Tom Hickey Published 2023-10-06 Update this page