Fork me on GitHub

Could someone explain this result? I thought that the value of an atom is always fully realized (not lazy), so I would expect the pr-str to take much less time.

=> (let [a (atom (take 10 (repeatedly #(Thread/sleep 1000))))]
    (time (pr-str @a)))
"Elapsed time: 10043.797237 msecs"


You're deref'ing the atom to get its value -- which is a lazy seq -- and then you're printing it to a string which is realizing the value.


So the 10 seconds is the time it takes pr-str to realize the take 10 -- the deref @a would have been near-instantaneous.


user=> (let [a (atom (take 10 (repeatedly #(Thread/sleep 1000))))]
         (time @a))
"Elapsed time: 0.007343 msecs"


An atom can contain anything -- it's just a container, and it doesn't "do" anything to its contents.


^ @wei does that help?

Alex Miller (Clojure team)04:01:34

well, it should only contain immutable values since the swap! function can be applied more than once in the case of concurrent updates


@seancorfield I see, so if I want the value to be realized before any derefs, I'd need to do that explicitly, like wrap the computation with doall. thanks for the insight


Yes, the same applies to laziness vs eagerness anywhere in Clojure really.

eccentric J07:01:11

I’m thinking of writing a boot task for replacing shortcodes in a markdown file using user-defined functions that return hiccup. Based on other libs I think there should be a defshortcode macro for defining them. How are those handled in other libs? Does it update an atom with a map of properties and a function body?

eccentric J07:01:36

I think data wise it’s important to know the defined shortcodes up front


is there any way to run some simple fns inside a clojure jar on android with a much faster startup speed?


how are people dealing with communication between components in stuartsierra/component?


Two components can communicate by one of them depending on another and using it. Do you have some other communication in mind?


Well, I might misunderstand something regarding the usage of component... So let's say I have a DB and Web components. The Web component depends on the DB one to do responses with values from the DB. But if I want to change the DB from Web, the state is within DB and cannot be changed from Web.


right now I'm just doing the DB as a simple map that get's stored/load to/from disk. Seemingly, I need to implement this as global state together with the DB component, but then I'm relying on global state...


The web component has a refererence to the db component, so it can read and write to the DB. I don’t understand your problem.


A DB is one huge global mutable variable, so that seems OK


you can model the DB with an atom that has a map in it


started trying out spec after having used schema and core.typed. one thing I noticed, compared to core.typed, spec’ing records is kind of laborious and overly verbose. is this something spec proper would ever address (even if just a macro) or should every one fend for themselves and write their own macros? I suppose there’s a third option which is the core team wants to discourage the use of records and/or their use with spec?

Alex Miller (Clojure team)16:01:21

kind of a latent question

Alex Miller (Clojure team)16:01:54

you can spec them as maps with s/keys and :req-un

Alex Miller (Clojure team)16:01:07

there are some ideas we have in spec 2 that might apply better but TBD


yep, I have, and it’s gross. =P we wrote a macro to fix that, but curious if the need to write such a macro indicates we’re using Clojure in a way not intended by the core team


(or if it’s just because spec is alpha)

Alex Miller (Clojure team)16:01:48

nah, just have never resolved what to do about records

Alex Miller (Clojure team)16:01:10

spec is centered around the idea of semantics associated with (qualified) attributes

Alex Miller (Clojure team)16:01:42

records sit in a weird place with that as the attributes are unqualified but records types themselves are qualified

Alex Miller (Clojure team)16:01:53

we’ve kicked around a bunch of ideas but never got something we liked


yeah, exactly part of the pain I was feeling with registering specs for record fields


ok, thanks for the info. wanted to make sure I wasn’t missing anything about the design or philosophy of spec

Alex Miller (Clojure team)16:01:17

nope, just some unfinished business


Hi guys, I am in doubt about what is the better way to solve the following problem. Scenario: Base: {:response [{:users [{:id 1} {:id 2}]} {:users [{:id 3} {:id 4}]}]} Path to: [:response :users] Replace with: [[{:id 1, :name "Rafa"} {:id 2, :name "Ana"}] [{:id 3, :name "Jonas"} {:id 2, :name "Leo"}]] Expected: [{:users [{:id 1, :name "Rafa"} {:id 2, :name "Ana"}]} {:users [{:id 3, :name "Jonas"} {:id 2, :name "Leo"}]}] I am thinking about recursion but I would like to know if there is a better way (using something like clojure.walk). Any thoughts?


what does the data structure containing the :names look like?


Sorry, I was not clear in my problem... It is not a fixed structure. It's like this: Given a base, path and "Replace with data", return base replaced with data


i.e (assoc-in original-data [:response :users] new-data)


The problem with using assoc-in is that the path don`t know if some key, like :users, is a list or not.


okay, now I see what you mean. is this part of a larger example? otherwise it might be easier to wrap the new data structure in :users:

(def new (mapv #(hash-map :users %) new-data))
and then (assoc old-data :response new)


is :id unique?


:id is just a key... Could be anything and could not exist. I am trying now to manipulate the path. So, using the previous example, generate something like: [:response 0 :users] and [:response 1 :users]


I highly recommend Specter for things like this:


here’s an example:

user=> m
{1 {:id 1, :name "Rafa"},
 2 {:id 2, :name "Ana"},
 3 {:id 3, :name "Jonas"},
 4 {:id 4, :name "Leo"}}

user=> base
{:response [{:users [{:id 1} {:id 2}]} {:users [{:id 3} {:id 4}]}]}

user=> (transform [:response ALL :users ALL] #(get m (:id %)) base)
{:response [{:users [{:id 1, :name "Rafa"} {:id 2, :name "Ana"}]}
            {:users [{:id 3, :name "Jonas"} {:id 4, :name "Leo"}]}]}


basically, for problems like this the details matter: exactly what the input is, what the data you want to place there instead etc. determines what the best approach is


but for the general problem of “replace something in a nested data structure with something else” Specter is IMO the way to go 🙂


Nice! Thank you! I will give it a shot =D


(clojure.walk/postwalk-replace (into {} (juxt #(select-keys % [:id]) identity) replacements) base)


You can definitely look at specter but to modify nested data structures in clojure using the "core library" you also have zippers. It takes a bit of playing around to get used to them (if you're not already) but once you know them you will be able to apply them in many scenarios.


@lucelios It looks like you want to join on the :id attribute. See


Nice! Thank you very much. But Can I use it lists that have maps and lists... ?


The changelogs of Clojure only go back to 1.3. I want to know if I remember this correctly: binding was allowed to rebind any var instead of only dynamic vars in the early versions of Clojure. Later on you could only do that with dynamic vars. with-redefs was introduced for rebinding the root values of vars e.g. for testing. Was that related to the change to binding?

Alex Miller (Clojure team)21:01:08

by which I’d say, yes


is there a nice idiomatic way to take a vector of maps [{:a 1 :b 2} {:c 3 :d 4}] and turn it into a map based off some key in the vec’s map? {1 {:a 1 :b 2} 3 {:c 3 :d 4} ...?


obviously a reduce would work, but it feels icky


(reduce #(assoc %1 (:the-key %2) %2) {} the-vec)


(now i see that the above is confusing, assume each map entry in the vector has the same keys)


(into {} (map (juxt :a identity)) coll)


interesting … seems weird to juxt with an identity, but necessary because of how into works I assume? takes [k v] pairs


yes you want a sequence of [(:a thing) thing] as your key value pairs which will go into the map


! group-by is exactly it, thanks @hiredman


well, it seems you assume that the vector of maps has a unique value for the same key in each map?


yes, i do — which fits for this particular dataset


good heads-up thinking though


so then it’s slightly different than group-by. we have a function called index-by for that, I can look it up


(defn index-by
  "Returns a map which indexes values by the result of calling kfn
  with given value."
  ([kfn values]
   (index-by kfn values nil))
  ([kfn values flat?]
   (tzipmap (map kfn values) values flat?)))


(where tzipmap is a transient-based version of zipmap)


i think the (into {} (map (juxt :a identity)) coll) will use transients for free because of into


could be, this code probably stems from before transducers ,etc.


there's the similar clojure.set/index as well - allows multiple relations to index and multiple matches for each value of the index

noisesmith22:01:50> (clojure.set/index [{:a 0 :b 1} {:a 1 :b 1}] [:a])
{{:a 0} #{{:a 0, :b 1}}, {:a 1} #{{:a 1, :b 1}}}


i love clojure.set, i use it almost everywhere


its so much easier for me to think about data as just sets and joins/unions/etc


woah. that’s a great idea for a tool…


where has this been all my life


set/index comes up first when you use [{:a 1} {:a 2}] [:a] as the args.


I’m spinning up some old projects with lein repl and getting this error:


No such var: nrepl.transport/uri-scheme


I have lein 2.8.3, clojure 1.8.0


I clearly have something out of sync somewhere


downgrade to lein 2.8.1 and try


yes | lein upgrade 2.8.1


yeah - lein changed nrepl versions with a recent release, and that could break old projects if they or their middleware relied on the way nrepl used to work


maybe you have some incompatible nrepl in your profiles.clj?


it could break all your projects if your profiles.clj pulled in a middleware for the old nrepl


Yes, I was hoping to use an older project to do some cider hacking. And it’s complaining about middleware as well. I feel a bit lost, lol.


Everything used to just work


I’m sure the new stuff is great, of course 😉


well, the CIDER maintainer also maintains nrepl, so they should at least evolve together now


ok, I have a repl… that’s good…. now let’s try cider….


Hmm. So for CIDER… can I upgrade the deps and the latest CIDER while keeping lein at 2.8.1?


no unfortunately. CIDER was straddling both tools.nrepl and nrepl/nrepl through 0.19 but the most recent 0.20 dropped tools.nrepl support. now the entire application needs to be newer nrepl throughout


So… if I want to make the leap… is there an upgrade guide?


we can chat in #cider but just check your deps for tools.nrepl.


Cool, thanks!