clojuredesign-podcast

samumbach 2025-06-17T20:30:25.167479Z

Would love to hear folks experiences with and thoughts about namespace-qualified keywords -- I was thinking about this particularly in the context of the current podcast series. I love the idea of passing maps around and being able to sneak any potentially useful context around in those maps and using namespace-qualified keywords as your map keys avoids potential name collisions and documents who is responsible for that data (and serves to group related keys together -- though same could be done by putting multiple things together in a sub-map). That being said, I often use keywords as functions and use key-based destructuring, and both of these are less convenient with namespace-qualified keywords than with "bare" keywords. Further, when there's a mix of :some.namespace/foo , ::foo, and ::somealias/foo all referring to the same keyword, it's more difficult to track down all the references to a given keyword. Am I doing it wrong? Do I just need to embrace namespace-qualified keywords everywhere and get used to it (until it doesn't feel inconvenient anymore)?

samumbach 2025-06-17T20:32:28.832529Z

Or maybe it's just better to avoid the ::kw and ::somealias/kw syntax and stick to :some.namespace/foo everywhere?

2025-06-17T21:14:25.704689Z

::kw causes tons of problems, and I generally avoid it unless it's more or less a private member.

2025-06-17T21:14:43.557499Z

::alias/kw works with tooling just fine

2025-06-17T21:15:17.015049Z

at least it does with intellij. I would assume kondo, cider, and Calva all have proper support as well

2025-06-17T21:16:13.036729Z

that said, for all the reasons you listed, I tend to type out a short namespace anyways

2025-06-17T21:16:28.517199Z

:aws.s3/key or :user/name

2025-06-17T21:17:07.054859Z

you only need a long namespace when you're writing a library

2025-06-17T21:19:41.554759Z

when you use a short keyword namespace, there's also no need to make it align with a particular code namespace

pez 2025-06-17T21:26:55.687969Z

I also tend to avoid ::kw. And I tend to go with namespaced keywords that are not aligned with actual namespaces. I call it “synthetic” namespaces. Calva (by proxy of clojure-lsp/clj-kondo) loves all kinds of namespaced keywords.

❤️ 2
borkdude 2025-06-17T21:31:22.431289Z

I was asked recently on a podcast if I would change anything about Clojure. I couldn't think of anything, but I wish I had said that I would probably like to remove features instead of adding them. E.g. *print-namespace-maps* , but mostly because I feel the pain when writing tooling for those features 😅

2025-06-17T21:32:54.656059Z

I also dislike that feature and how difficult it is to disable it.

2025-06-17T21:33:09.550819Z

But ‘tis a mere nuisance

borkdude 2025-06-17T21:34:13.844529Z

Yeah, not a big deal

samumbach 2025-06-17T22:22:41.796649Z

Thanks for the insight @potetm @pez @borkdude 😄 Do any of y'all use the [{:some.ns/keys [foo bar baz]}] destructuring syntax to good effect?

neumann 2025-06-18T21:58:17.425229Z

I also use {:foo/keys [bin baz]} often, but if I just have one thing, I'll use the full key name eg. {the-thing :the/thing}

neumann 2025-06-18T21:59:43.102409Z

Here's an example from actual code:

{:cache/keys [url-settings settings]
 :device/keys [registered? started?]
 :websocket/keys [connected?]} data

🤘 1
neumann 2025-06-18T22:00:42.298789Z

I have state information that looks like:

(defn initial-data
  []
  {:device/connections {}
   :device/duplicate? false
   :device/id nil
   :device/name nil
   :device/registered? false
   :device/started? false
   :device/type nil
   :org/id nil
   :websocket/connected? false})

Casey 2025-07-24T09:44:30.852159Z

The :entity/name thing bothers me a lot, I hate shadowing core fns. I often end up making more verbose attributes like :device/device-name :book/book-id so that code using {:book/keys [book-id]} (vs, just id ) is more readable. Some people I've worked with definitely disagree though. I suppose its about optimizing for different things: reading code vs writing code perhaps

👍 1
2025-07-24T12:06:48.639679Z

I’ve wasted more time than i want to admit from shadowing fns (not just core). I just don’t do it. Going longer is one option, but going shorter is as well.

💯 4
samumbach 2025-07-24T12:08:38.910339Z

Agreed!! I think clj-kondo has a linter to catch shadowing, you just have to set up a list of cars you want to avoid shadowing.

Casey 2025-07-24T14:01:00.281079Z

I never actually considered going smaller, opened my eyes today

❤️ 1
samumbach 2025-07-24T15:29:44.348249Z

I like to use the names Clojure.core uses: k, v, m, nm, ...

samumbach 2025-07-24T15:30:34.683579Z

(for binding and parameter names; I think nm is awkward in an API)

pez 2025-06-17T22:23:46.420089Z

I use that all the time!

👍 1
pez 2025-06-17T22:27:25.941589Z

I try to avoid overshadowing Clojure core names. So even if a keyword like :user/name makes sense, destructuring it like [{:user/keys [name]}] can cause troubles. Especially together with tools like Snitch. So it will be :user/user-name .

2025-06-17T22:28:19.448429Z

I don’t, but it’s mostly a preference thing. I’ve been bitten by shadowing a ton so I shorten all names to abbreviations by default to avoid it.

2025-06-17T22:30:09.252799Z

{n :user/name}

2025-06-17T22:30:13.098269Z

Eg

pez 2025-06-17T22:31:09.902319Z

It’s wonderful, I think:

(defn foo [{:foo/keys [...]
            :bar/keys [...]}]
  ...)

samumbach 2025-06-17T22:31:20.047249Z

Agreed about shadowing -- I use nm, k, v, ks, vs, m etc; shadowing map has bitten me too many times

2025-06-17T22:31:56.396839Z

most people recoil when they see the abbreviations I use, but everyone who’s worked with me ends up liking it.

2025-06-17T22:32:09.950459Z

the abbreviations are always consistent, which helps.

👍 1
pez 2025-06-17T22:32:34.265169Z

Also sometimes [{:keys [foo/this bar/that]}]

samumbach 2025-06-17T22:33:10.235389Z

I use the abbreviations already used in core whenever I can

➕ 2
pez 2025-06-17T22:34:04.774389Z

x ❤️

2025-06-17T22:34:48.846909Z

Yeah I basically do that all over the place. organization -> org, last-modified-date -> lmd, username -> un, etc

2025-06-17T22:35:51.517589Z

used consistently, it becomes an easy shorthand. people would even say them out loud

pez 2025-06-17T22:36:52.837969Z

I tend to use longer names. And short ones for functions sent to higher order functions in core and libs.

pez 2025-06-17T22:38:15.878439Z

acc for the reduce accumulator. I know some people hate it, but to me it just says exactly what I want it to say. It is the accumulator. 😃

➕ 4