This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-01-17
Channels
- # aleph (3)
- # announcements (12)
- # beginners (80)
- # boot (3)
- # braveandtrue (16)
- # calva (3)
- # cider (82)
- # clojure (100)
- # clojure-art (3)
- # clojure-dev (79)
- # clojure-estonia (1)
- # clojure-europe (4)
- # clojure-finland (15)
- # clojure-indonesia (1)
- # clojure-italy (20)
- # clojure-nl (4)
- # clojure-spec (24)
- # clojure-sweden (2)
- # clojure-switzerland (1)
- # clojure-uk (99)
- # clojurescript (145)
- # cursive (8)
- # data-science (7)
- # datomic (26)
- # emacs (4)
- # figwheel-main (20)
- # fulcro (8)
- # graphql (3)
- # hoplon (2)
- # jobs (1)
- # kaocha (5)
- # leiningen (2)
- # liberator (19)
- # off-topic (16)
- # pathom (9)
- # perun (1)
- # portkey (2)
- # re-frame (17)
- # reitit (1)
- # shadow-cljs (26)
- # spacemacs (7)
- # vim (49)
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?
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.
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?
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.
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?
kind of a latent question
you can spec them as maps with s/keys and :req-un
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
nah, just have never resolved what to do about records
spec is centered around the idea of semantics associated with (qualified) attributes
records sit in a weird place with that as the attributes are unqualified but records types themselves are qualified
we’ve kicked around a bunch of ideas but never got something we liked
ok, thanks for the info. wanted to make sure I wasn’t missing anything about the design or philosophy of spec
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?
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
ahh, then you can use assoc-in
! https://clojuredocs.org/clojure.core/assoc-in
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)
: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: https://github.com/nathanmarz/specter/
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 🙂
(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 https://clojuredocs.org/clojure.set/join
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?
https://github.com/clojure/clojure/commit/178d8c42609d899208e745b76b89297c4287c078
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} ...
?
(now i see that the above is confusing, assume each map entry in the vector has the same keys)
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
well, it seems you assume that the vector of maps has a unique value for the same key in each map?
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?)))
i think the (into {} (map (juxt :a identity)) coll)
will use transients for free because of into
there's the similar clojure.set/index
as well - allows multiple relations to index and multiple matches for each value of the index
egret.run=> (clojure.set/index [{:a 0 :b 1} {:a 1 :b 1}] [:a])
{{:a 0} #{{:a 0, :b 1}}, {:a 1} #{{:a 1, :b 1}}}
this finds group-by
as the closest built-in thing:
https://re-find.it/?args=%5B%7B%3Aa%201%7D%20%7B%3Aa%202%7D%5D%20%3Aa&ret=%7B1%20%7B%3Aa%201%7D%202%20%7B%3Aa%202%7D%7D&more=true
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
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
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?
Cool, thanks!