clojure-dev 2025-05-22

Is there any writing on why PersistentQueue isn't more prominent in Clojure? It was built and iterated on through 1.0 and then work on it cooled off. it doesn't have the same "first-class" status as lists, vectors, maps, and sets with a reader macro, creation and coercion functions, or any references in clojure.core except for peek and pop.

πŸ‘€ 1

which is surprising to me, given that it was originally written in 2006 (https://github.com/clojure/clojure/commit/1a399df8f3f3bcb9d3a92a584fa9714832ab550f) and fleshed out well before first class sets were added

Alex Miller is typing, gotta hurry to post something stupid. I'd say it is probably because you rarely need pure algorithmic queues. Most time you reach for queues you need them for synchronization, and PersistentQueue doesn't offer that.

πŸ˜‚ 4
Alex Miller (Clojure team) 2025-05-22T18:52:06.324959Z

the queue stuff is really most useful in single-threaded contexts and those just don't come up that frequently. if you're using them statefully they need to be wrapped into an atom or whatever and at that point you're probably better off just using one of the jdk concurrent queues

Alex Miller (Clojure team) 2025-05-22T18:53:05.154459Z

that said, I do have on my list of things that I think it would be useful to add queue constructor (so you don't have to reach into PQ) and queue? predicate

πŸ‘ 1

Damn, feeling like a boss. @puredanger sniping - success.

πŸ˜‚ 8

yeah seeing the Asks about queues brought this to mind, so i decided to look at the git history for inspiration and didn't find anything useful

Alex Miller (Clojure team) 2025-05-22T18:54:26.428159Z

the one time I usually use it is in doing like a walk over a tree and maintaining loop state (children etc)

I've created a PQ memory leak ticket in the past, so I must have used it for something. https://clojure.atlassian.net/browse/CLJ-2397

πŸ‘ 1
Alex Miller (Clojure team) 2025-05-22T18:56:06.816149Z

I do not think #queue is worth doing

Because of a general distaste for data readers?

Alex Miller (Clojure team) 2025-05-22T18:58:33.082629Z

it's just not common enough to be worth doing imo

Alex Miller (Clojure team) 2025-05-22T18:59:14.743409Z

should you even be edn serializing a queue?

πŸ’‘ 1
Alex Miller (Clojure team) 2025-05-22T18:59:46.597919Z

data readers are great, I just think they should be used sparingly :)

(def queue PersistentQueue/EMPTY) should probably be enough, but it would squat a tasty name.

i think there was another queue related jira that i'm forgetting now... something about how the code path for printing queues never reaches its #= print-method because it implements persistent list or something

Alex Miller (Clojure team) 2025-05-22T19:02:23.528139Z

lol :)

7

my feeling is that queues would be used more if they were better supported by clojure core, with or without a data reader

before clojure, i almost never used sets because why bother? now i can't imagine life without 'em lol

Alex Miller (Clojure team) 2025-05-22T19:04:29.683809Z

yeah that seems like a bug that should be fixed

Alex Miller (Clojure team) 2025-05-22T19:04:51.810899Z

I use Java's queues more than Clojure's

πŸ‘€ 1
☝️ 3

even tho they're not persistent? interesting

Alex Miller (Clojure team) 2025-05-22T19:05:34.045879Z

usually you are using a queue to communicate across threads and then you need concurrency and Java has lots of great options

πŸ‘ 1

Transducing contexts are pretty amenable to mutability that doesn’t escape a small visible area

When you need "Clojure queues", you usually pick core.async channels

Alex Miller (Clojure team) 2025-05-22T19:06:14.381179Z

yeah, or those, depends on context

why doesn't PQ offer synchronization?

Alex Miller (Clojure team) 2025-05-22T19:10:10.108809Z

it's immutable ?

gotta actually remember what words mean before asking questions

Alex Miller (Clojure team) 2025-05-22T19:12:02.698589Z

if you put it in an atom then you're often both peeking it and conj or popping it, it's just not great for this. with Java's concurrent queues you have all the options - block, try, etc

Alex Miller (Clojure team) 2025-05-22T19:12:26.040809Z

the deques let you do it either end

Alex Miller (Clojure team) 2025-05-22T19:13:00.170519Z

Doug Lea probably spent a year optimizing it :)

that's interesting, thanks

Alex Miller (Clojure team) 2025-05-22T19:21:28.443699Z

single threaded queues are good for tracking arbitrary depth stuff in tree-like form in an algorithm. mostly we deal with regular collections of known-shaped things not arbitrary things to deal with generically, so walking trees of code (but we usually take a local view ala walk or zip), or trees of data (quickly you want a graph api like Loom or a datalog database).

Alex Miller (Clojure team) 2025-05-22T19:22:20.466339Z

the one prominent place I can remember using a PQ is in the tools.deps dep expansion loop which has a queue of nodes to visit, doing a breadth-first walk

πŸ‘ 1

we use it in one spot identifying the shortest join between two tables: (loop [paths (conj clojure.lang.PersistentQueue/EMPTY [start])

I’ve used it for breadth first walking algos before. It’s the canonical data structure for it!

πŸ‘ 1

(woah, cloogle is cool!)

😁 2
βž• 2
Alex Miller (Clojure team) 2025-05-22T19:34:45.518429Z

grep.app reports 187 https://grep.app/search?f.lang=Clojure&q=PersistentQueue%2FEMPTY of PQ/EMPTY across github, which is pretty small

Alex Miller (Clojure team) 2025-05-22T19:36:19.238889Z

tbh, I trust http://grep.app more than GH's search :)

Alex Miller (Clojure team) 2025-05-22T19:37:04.814929Z

oh, I searched for EMPTY above so yours is wider, seems to catch some partial class names etc

yeah, we searched different stuff

I count 648 class usages of clojure.lang.PersistentQueue in dewey across 257 repos.

i wonder how many folks have defined #queue lol

or queue? that checks (instance? ...)

At work, in ~150k lines of Clojure, we have two PQ/EMPTY (in atoms!) in src and one PQ/EMPTY in a test.

Oh, one of those src uses is in debug-only code. So, one real usage πŸ™‚

Alex Miller (Clojure team) 2025-05-22T19:58:54.265689Z

I believe cljs has #queue right?

Alex Miller (Clojure team) 2025-05-22T20:01:17.078929Z

seems like most uses are people doing #queue [] , would much rather have (queue) for that

what they want is #[] 😈

Alex Miller (Clojure team) 2025-05-22T20:06:05.102999Z

well I definitely don't think queue is important enough to have syntax like that :)

hah yeah, that won't ever happen

Alex Miller (Clojure team) 2025-05-22T20:06:22.664689Z

does cljs have the queue fish stuff?

Alex Miller (Clojure team) 2025-05-22T20:08:36.801659Z

something used to print queues as <-(1 2 3)-< have no idea how to search for that

🀩 1
Alex Miller (Clojure team) 2025-05-22T20:09:48.917369Z

wacky

πŸ˜‚ 2

❯ clj
Clojure 1.12.0
user=> (into clojure.lang.PersistentQueue/EMPTY [1 2 3])
#object[clojure.lang.PersistentQueue 0x5e840abf "clojure.lang.PersistentQueue@7861"]
user=> (pp)
<-(1 2 3)-<
nil

🀯 2
Alex Miller (Clojure team) 2025-05-22T20:11:17.285559Z

maybe I'm the only one that calls that a queue fish :)

Alex Miller (Clojure team) 2025-05-22T20:11:49.860679Z

oh, it's in Joy of Clojure whew

rust has turbofish right? i think fish is common enough suffix?

πŸ€·β€β™‚οΈ 1

> The ::<Vec<i32>> part is the turbofish and means

LLM pretty decisively disagrees with me that it’s a common enough suffix haha.

it instantly made sense to me

it's a fun way to print it if there's no tag for it

same here. which is why i assumed it was part of a bigger tradition since i knew of the rust turbofish

Alex Miller (Clojure team) 2025-05-22T20:21:03.721039Z

I blame chouser and fogus :)