clojure-dev

2025-05-22T18:44:05.770039Z

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
2025-05-22T18:45:44.893409Z

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

oyakushev 2025-05-22T18:51:44.100539Z

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
oyakushev 2025-05-22T18:53:35.214489Z

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

πŸ˜‚ 8
2025-05-22T18:54:22.743179Z

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)

2025-05-22T18:54:46.675299Z

(`queue` and queue? ask: https://ask.clojure.org/index.php/3821/add-queue-and-queue-to-clojure-core)

oyakushev 2025-05-22T18:56:01.155369Z

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

2025-05-22T18:57:38.943199Z

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
2025-05-22T18:59:45.489629Z

🀷

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

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

oyakushev 2025-05-22T19:00:05.223129Z

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

2025-05-22T19:00:34.099349Z

reader literal and print support for queues Ask: https://ask.clojure.org/index.php/3365/implement-reader-literal-support-persistentqueue-structure

2025-05-22T19:01:53.790159Z

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
2025-05-22T19:02:35.301309Z

ah here we go, paula's find: https://ask.clojure.org/index.php/10575/why-does-evaluating-a-queue-not-return-itself

2025-05-22T19:03:56.471629Z

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

2025-05-22T19:04:14.473309Z

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
2025-05-22T19:05:06.768459Z

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
dpsutton 2025-05-22T19:05:52.553769Z

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

oyakushev 2025-05-22T19:05:59.695809Z

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

2025-05-22T19:09:34.397829Z

why doesn't PQ offer synchronization?

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

it's immutable ?

2025-05-22T19:10:31.505239Z

oh duh lol

2025-05-22T19:11:11.699779Z

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 :)

2025-05-22T19:17:29.116089Z

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
dpsutton 2025-05-22T19:25:01.934879Z

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

phronmophobic 2025-05-22T19:31:13.557729Z

It seems like it's used in a number of different libraries, https://cloogle.phronemophobic.com/name-search.html?q=clojure.lang.PersistentQueue&tables=java-class-usages.

πŸ‘€ 1
2025-05-22T19:31:15.404449Z

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

πŸ‘ 1
2025-05-22T19:31:39.126179Z

(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

2025-05-22T19:35:15.161679Z

github itself has 2.6k of persistentqueue itself: https://github.com/search?q=PersistentQueue+language%3Aclojure&type=code

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

2025-05-22T19:37:18.872819Z

yeah, we searched different stuff

phronmophobic 2025-05-22T19:46:36.015099Z

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

2025-05-22T19:48:11.613919Z

i wonder how many folks have defined #queue lol

2025-05-22T19:48:21.670119Z

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

seancorfield 2025-05-22T19:50:41.113279Z

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

seancorfield 2025-05-22T19:51:33.846519Z

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?

2025-05-22T19:59:03.600539Z

yes

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

2025-05-22T20:04:28.243349Z

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 :)

2025-05-22T20:06:15.329679Z

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
dpsutton 2025-05-22T20:09:54.143379Z

❯ 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

dpsutton 2025-05-22T20:12:15.360639Z

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

πŸ€·β€β™‚οΈ 1
dpsutton 2025-05-22T20:13:00.830229Z

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

dpsutton 2025-05-22T20:14:22.370829Z

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

2025-05-22T20:14:41.970059Z

it instantly made sense to me

2025-05-22T20:15:07.258709Z

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

dpsutton 2025-05-22T20:15:11.356199Z

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 :)