Fork me on GitHub
#clojure
<
2023-07-19
>
diego.videco16:07:03

Hey all, is there are consensus with regards to best practices when using keywords? I tend to like Eric Normand’s ideas about using double colon keywords, and often prefer to just use namespaced keywords that don’t refer to an actual namespace (like :not-a-real-ns/keyword). https://ericnormand.me/issues/purelyfunctional-tv-newsletter-430-use-keyword-notation-for-unique-values However I’ve also seen this post, which sort of advices an opposite approach: https://blog.jeaye.com/2017/10/31/clojure-keywords/ Would really appreciate hear about your thoughts, experiences and advice with using keywords.

p-himik16:07:47

There's no consensus and you'll see all approaches used in the wild. I myself use both that you mentioned and also nested maps with only plain keywords, sometimes within the same project - depends on the context.

4
Joshua Suskalo16:07:11

I wonder how people would consider

(ns com.company.ns
  (:require
    [com.company.ns :as-alias a]))

::a/blah
which neatly solves the problem of not being transportable while also keeping concision

Alex Miller (Clojure team)16:07:27

just a note that that latter blog blog pre-dates the 1.11 feature of :as-alias which is a big help in the specific case of using qualified keywords that don't refer to a loadable namespace

Alex Miller (Clojure team)16:07:36

the idea here is that: 1. qualified keywords ("qualified" used here specifically as whether they correspond to a namespace is orthogonal) are useful for disambiguating names in global attribute space 2. but qualifiers can be long, so it's helpful to use aliases 3. but aliases (in :require :as) load the namespace, which makes it hard to use qualifiers that don't correspond to a namespace 4. which is why we added :as-alias

Alex Miller (Clojure team)16:07:30

so: use qualifiers to disambiguate, use aliases with either :as or :as-aliase as appropriate to type less

👍 2
Alex Miller (Clojure team)16:07:18

all that said, keywords exist in a context, and not all contexts need global disambiguation. if you are passing options to a function, probably unqualified is sufficient, etc

👍 2
Noah Bogart17:07:50

are there performance penalties/differences between top-level functions and inline functions in a let block?

Alex Miller (Clojure team)17:07:27

they're both compiled to function classes so my guess is no difference. but as a wise man named Rich once told me, why guess when you can measure? :)

😂 2
Noah Bogart17:07:31

that's a good point.

Alex Miller (Clojure team)17:07:12

I guess a top-level function may require a var lookup whereas inline does not so that is one possible difference (that is independent from the function itself)

Alex Miller (Clojure team)17:07:30

if direct linked, that would presumably not be relevant

Noah Bogart17:07:04

cool, that makes sense. my small tests didn't show much difference so thanks for the clarity

Joshua Suskalo17:07:47

Another difference between them would be that inline functions in a let block would construct instances (and if you don't close over anything it would have no instance variables) which requires an allocation, but it's reasonably likely that after some iterations the JVM would be able to realize that the instance only exists to call a static method, and optimize it out.

hiredman17:07:46

even without optimizations the jvm is extremely good at allocating

hiredman17:07:10

like just stupifyingly good

Joshua Suskalo17:07:14

Absolutely, and on JDK 11+ even better for this case because of the G1 collector being the default.

Joshua Suskalo17:07:58

On JDK 8 there is a small possibility of this becoming a performance concern, but it's unlikely and you'd have to measure to know.

Joshua Suskalo17:07:08

and it would have to be an extremely hot loop.

Ben Sless17:07:37

There are some other elements to consider: • top level defns emit classes with static methods • how everything works with the JIT compiler ◦ will inline forms get optimized the same way as a top level def? • direct linking (once you eliminate var lookups, the JIT compiler can freely inline method calls

Alex Miller (Clojure team)18:07:58

I take back my initial reaction, it's not the same and it's a complicated question :)

😂 6