Fork me on GitHub

I saw somewhere that *ns* isn't bound during AOT compilation but I'm wondering if that's true. In particular, def's docstring says: > Creates and interns a global var with the name > of symbol in the current namespace (*ns*) or locates such a var if So I guess it must be set? The compiler seems to be setting *ns* here: (called here: My use case is that I want to automatically define vars based on their "definitions" in a hashmap instead of manually calling def. I wanted to use (intern *ns* ... for that purpose Something like:

(def config-keys {:key1 {} :key2 {}})
(defn- intern-config-var [[config-key _]]
  (intern *ns*
          (symbol (name config-key))
          (read-env config-key)))
(run! intern-config-var config-keys)
which should produce vars key1, key2, etc.


A common trick is to have (def my-ns *ns*) at the top of the namespace and then use my-ns subsequently.


That way my-ns is defined to be the actual namespace (at load/compile time) rather than whatever *ns* is bound to at run time.


So given that I'm calling this immediately (the last line) as a top-level form there shouldn't be any difference, right? When would this be a problem? If intern-config-var was public and called from another ns?


*ns* is always set during compilation


The tricky thing is compilation and runtime are interleaved in such a way that people often expect *ns* to have the same value at runtime as it has at compile time, which is basically only the case in the repl


Your use case is likely fine

👍 3

Maybe not clojure-specific, but anyone has a clever trick for caching Maven dependencies that will survive unrelated changes to project.clj / deps.edn?


mmm, I had forgotten about this that's the answer. I think I had worked for a while on projects not featuring that snippet


Tying the maven cache to the sha of the dependencies seems silly. You should share the same m2 everywhere for every build as much as possible


With a high churn in dependencies the cache will be indefinitely growing though. I encountered problems with this in a js project a while back. Restoring the cache took more time than downloading the dependencies at some point. The workaround was including a timestamp in the cache-key.


how can i turn a org.httpkit.BytesInputStream into edn?


(clojure.edn/read ( <org.httpkit.BytesInputStream>))


no doesn't work


class cannot be cast to class ( and are in module java.base of loader 'bootstrap')


One more level of wrapping might help. PushbackReader constructor instantiates from a Reader - a quick scan of the class shows.


clojure.edn/read expects a pushbackreader


seems to be it


While this works - do you need the inner-most PushbackInputStream? I think the reader can take the httpkit object - which I believe extends InputStream

Jim Newton13:07:59

the documentation of cl-format claims that it is fully compatible with the CL version of format. However, in CL the ~A directive (print aesthetically) pretty-prints the corresponding argument. For example (format out "~A" some-list) outputs the same as (pprint some-list out) However in clojure (cl-format out "~A" some-list) outputs the contents of some-list all on a single line. Does anyone know whether it is possible to make this work correctly? I've seen the dynamic variable *print-pretty* which seems to have no effect on ~A

Jim Newton13:07:24

if not, is there a way to tell the default format to print the corresponding argument as if by pprint ?

Jim Newton13:07:23

according to line 1338 of cl_format.clj it seems ~A dispatches to print-str rather than to some form of pprint-to-str .. I suspect that is a bug, because I don't see any comment there explaining how the pretty-printer is intended to be triggered here.

Jim Newton14:07:24

It seems like it should use something like (fn [data] (with-out-str (pprint data)) rather than print-str


At this point, it seems like making a post on would be worth it.


i want to add user keybindings to my emacs config for reloading/starting/stopping my integrant system. cider does not seem to expose any non-interactive functions for evaluating a clojure form. I want an emacs script that finds the system ns and evaluates the start/stop methods. how do i do this?


in other words, i want to be able to do all the cider interactive stuff non-interactively (programmatically in elisp)


I know some people make use of cider-refresh-before-fn and cider-refresh-after-fn


Set that in .dir-locals.el and you can ‘hook’ into cider-refresh to stop and start your system

Daniel Ziltener14:07:29

Is there an up-to-date core.cache adapter for Redis? I tried, but that doesn't work with the current Clojure version anymore


TIL about the lib :) last commit isn't too distant so I think the right thing in this case is opening an issue with a repro

Daniel Ziltener15:07:57

I ended up fixing the namespace, updating the dependencies, and opening a pull request 🙂


kudos 🚀


I’ve got a namespace with this var declaration:

(def yy protocols/ApiAuth)
I start REPL which loads this namespace. I do absolutely no reloads of any kind. And yet:
(identical? yy protocols/ApiAuth)
=> false
how is this possible

Alex Miller (Clojure team)15:07:56

what does protocols/ApiAuth eval to? I'm assuming a protocol?


I’ve been running into a bit of trouble with protocols lately, and I know that I need to have a clean target folder and if I reload the namespace with the protocol I need to reload all the namespaces with protocol implementations, but this one has been baffling. When I start REPL about a 100 namespaces get loaded due to being included from the core one. It seems that same protocol gets defined multiple times which is odd

Alex Miller (Clojure team)16:07:49

protocols are just maps, so you could compare them with to find things that are different. I'm guessing the :on key (the interface class) is different



(identical? (:on yy) (:on protocols/ApiAuth))
=> true
(identical? yy protocols/ApiAuth)
=> false

Alex Miller (Clojure team)16:07:17

well, it was just a guess. you can use to narrow it down

Alex Miller (Clojure team)16:07:50

I mean, the protocol gets updated as it gets extended, so you might be seeing an older version vs a newer version with different extensions


ah… maybe that’s the problem with my code


(s/def ::auth-token (partial satisfies? protocols/ApiAuth))

Alex Miller (Clojure team)16:07:24

when you def yy, you're just getting a point in time, not tracking updates


that spec fails for objects it shouldn’t fail for


I am guess it closes over a version of protocol without the necessary implementations in the map

Alex Miller (Clojure team)16:07:57

maybe? you might be better with using an anonymous function there instead so you're not evaluating early

Alex Miller (Clojure team)16:07:26

#(satisfies? protocols/ApiAuth %)


yeah that works as expected


Yeah, I recently encountered the same thing, using an anonymous function fixed it


well this is definitely a gotcha for most people


I think describes the same scenario, would you agree @U66G3SGP5?


( also relates, but from a performance point of view I guess)


it’s not a problem that it works that way, but it’s definitely unexpected by most


I think partial behaviour is not poorly described. What is surprising is that extending a protocol produces a new value…. in most languages type identifiers are immutable singletons and as most people grok protocols as some sort of type/interface abstraction, they get blindsided by this “type” identifier changing as new implementations are defined.

Alex Miller (Clojure team)18:07:41

I think that's a good insight. There are two "stateful" runtime constructs in Clojure - protocols and multimethods. As Clojurists we should not be surprised that state creates problems (like temporal coupling)

Alex Miller (Clojure team)18:07:02

but you can't have open dispatch systems without managing state over time to allow for late behavior extension

Alex Miller (Clojure team)18:07:57

I do think it is not immediately obvious what the tradeoff is in partial vs anon fn wrt evaluation and closures and that probably warrants a faq entry


yeah, I guess there are two different things here (which may or may not be obvious depending on your level of expertise): a) why (partial foo bar) isn't the same as a similar anonymous function (I'd guess this also applies to other HoF's too, like comp) and b) the value of a protocol may change when it's extended


I remember encountering the a) issue when adding instrumentation to a function foo, but had already defined some helpers with partial e.g. (def helper (partial foo 1)) -> calling helper with some incorrect args wouldn't trigger an instrumentation failure

Alex Miller (Clojure team)16:07:11

(identical? (:on yy) (:on protocols/ApiAuth))


Hi , I am sending this data in body in a put api

[{"topic":"xyz", "key":"abc", "message": "pqr"}]
I need to parse these params at handler one by one. Can someone suggest the cleanest way to do it?


build=> (require '[ :as json])
build=> (json/read-str "[{\"topic\":\"xyz\", \"key\":\"abc\", \"message\": \"pqr\"}]")
[{"topic" "xyz", "key" "abc", "message" "pqr"}]


Not as json string. but the parameters


(defn myFunc
      [{:keys [params]}]
              (let [
                    topic (:topic params)
                    key (:key params)
                    message (:message params)
Need to add the for loop to this


params usually isn't a vector like you posted above


but you could try [{{:strs [topic key message]} :params]


(defn foo [{{:strs [topic key message]} :params}]
  [topic key message])

(foo {:params {"topic" "t" "key" "k" "message" "msg"}})
#_-> ["t" "k" "msg"]


[ {"topic":"xyz", "key":"abc", "message": "pqr"}, {"topic":"xyz1", "key":"abc1", "message": "pqr1"}, {"topic":"xyz2", "key":"abc2", "message": "pqr2"}] ] Would it run for this one?


that's a different shape. what do you want your function to do?


generally, figure out how to make a function that takes one map with topic, key, and message, and then figure out how to do it multiple times

👍 3

This is the json body in my api request. Need to parse this data one at a time


ok. i'm not aware of any json libraries that will parse one entry at a time


but i suspect you mean you need to act one one "record" at a time, not parse one at a time


you just need to parse the json string? Or do you mean something else?


How do I write a tab literal character?