This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
I'm reading Joy of Clojure 2nd edition, I'm confused by one of the sample code:
boot.user=> (def add-and-get
#_=> (let [ai (java.util.concurrent.atomic.AtomicInteger.)]
#_=> (fn [y] (.addAndGet ai y))))
#'boot.user/add-and-get
boot.user=> (add-and-get 2)
2
boot.user=> (add-and-get 2)
4
boot.user=> (add-and-get 7)
11
boot.user=>
I don't understand, shouldn't there be multiple ai instance every time add-and-get is called?hey guys, I was trolled by my ignorance, I was trying to prove myself that binding is using threadLocal underhood and the code above I was expecting one result and got one completely different
(defn ^:dynamic my-max [a b] (max a b))
(defn find-max [x y]
(my-max x y))
(async/thread (binding [my-max min]
(do
(Thread/sleep 3000)
(async/thread
(println "Expecting: 20, Actual:" (find-max 10 20))))))
The async thread is using one thread pool underhood, right ? So the threadlocal is shared among all threads inside pool
@oliv dynamic vars are not threadlocals (althought they happen to use threadlocal under the hood). I used to think so and got bitten by the same kind of experience you just made. Then I read the source code for vars and binding conveyor functions, and now I just don't use dynamic vars anymore, because they're so overcomplicated and counterintuitive. If what you need is a thread local variable, just use java.lang.ThreadLocal.
Hey thanks @leonoel , my experience was to see how binding function works. Because inside the binding function body we could remap the var , but only inside binding body . Outside remains the same
And I went to source code and discover is using threadlocal , but how different threads share the same value is what I didn't understand yet
if you look at core.async/thread most of what it does is set up a copy of all the parent thread bindings to propagate them - it's intentional - future does the same thing
(the source, that is)
❤️ lovely , yeah just saw that @noisesmith
it's done by the frame mechanism, basically when you ˋfutureˋ or ˋsendˋ or ˋasync/threadˋ you capture the bindings of the current thread, and the new thread restores the bindings before doing its job
look e.g. here https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L2019
obviously the result is that you have shared mutable state between threads, which is definitely not what thread locality is
I've tried juxt/aero. But it feels like somethings are not doable with it. Like include an optional config file, only if it exists. Any suggestions?
@ttx You could do it by using merge
in the app. Maybe something like this would help:
(defn load-config
"Load configuration. Merge default values with
loaded configuration."
[]
(merge {:db {:host "localhost"
:user "temp"
:dbname "postgres"
:password ""
:port 5432}}
(when (file-exists? "config.edn")
(aero/read-config "config.edn"))))
Where file-exists?
would be something like
(defn file-exists?
"Check if file exists"
[file-name]
(.exists ( file-name)))
We use Crispin https://github.com/dunaj-project/crispin
with the main config as edn, and overwriting production vars with ENV or JVM flags
@henrik Thanks! Your solution definitely works. But I was looking into something which wouldn't make me change the code much. Tried hacking a custom 'resolver' which wraps around the default resolvers, but no luck; as resolvers emit file path, not content of the file. Poor design choice IMO.
@drowsy Good point. I'm fairly new in clojure and didn't yet dive into macros and protocols. Looks like it's the perfect opportunity. Thanks for the suggestion.
Where can I find docs of the new'ish syntax for destructuring namespaced keywords? In particular, I'm looking for the cleanest way to define a function that takes many (several dozen) un-namespaced keyword parameters as well as a few namespaced parameters (all in the same namespace, if that helps).
... found the answer to my immediate question: (defn f [{:keys [:a/x y z]}] [x y z])
. But, I did not find a doc that gives the current full grammar.
Perhaps https://clojure.org/guides/destructuring#_namespaced_keywords could be updated if not clear?
Hello, maybe someone can help me with a piece of code.
I have something like this:
["Name" "Price"]
and
`[ ["Foo" 100] ["Bar" 200] ]
and I want to merge them together to this:
`[ ["Name" "Price] ["Foo" 100] ["Bar" 200] ].
How can I do that?
Hi all 🙂 i already have a question about using clojure with emacs. Is there an easy keybinding to move whole key-value pairs up/down in the listing?
@a_duerrhauer - (into (vector ["Name" "Price"]) [["Foo" 100] ["Bar" 200]])
@mfikes - Thanks. I did not find that page. That, eventually augmented with the 1.9 namespaced keyword syntax, would be exactly what I needed.
also, if you want to overwrite based on keys, you can easily turn these into maps, merge with map-like semantics, and then return back to the sequence of vectors
(merge (into {} '(["key1" 2] ["key2" 3])) (into {} '(["key1" 5])))
{"key1" 5, "key2" 3}
this might be simpler as
(into {} (into [["key1" 2] ["key2" 3]] [["key1" 5]]))
@mfikes Hmm, so it is. Not sure why my google searches missed these. Mostly, I guess, the usual problem that it's hard to search for non-alphabetic syntax. Thanks!
(vector ["Name" "Price"])
is weird - why not just ["Name" "Price"]
?
there's :eval-in pprint
iirc
@oliv yeah if you add :eval-in pprint
to the top level of the project map, then run lein repl
or lein run
it will print everything, fully filled out and expanded and pprinted
why is this giving me a CompilerException? (unable to resolve symbol: f in this context):
(defn graphify [structure]
(cond
(set? structure) (mapcat graphify structure)
(vector? structure)
(mapcat
(fn [[a b]]
(concat
(let [f (fn [[a b]]
(let [A (cond (set? a) :set (vector? a) :vector (map? a) :map)
B (cond (set? b) :set (vector? b) :vector (map? b) :map)]
(case [A B]
[:set :set] (mapcat f (for [i a j b] [i j]))
[:set :vector] (mapcat (fn [i] (f [i (nth b 0)])) a)
[:set :map] (mapcat (fn [i] (f [i b])) a)
[:vector :set] (mapcat (fn [i] (f [(peek a) i])) b)
[:vector :vector] (f [(peek a) (nth b 0)])
[:vector :map] (f [(peek a) b])
[:map :set] (mapcat (fn [i] (f [a i])) b)
[:map :vector] (f [a (nth b 0)])
[:map :map] [[a b]])))]
(f [a b]))
(concat
(if (or (set? a) (vector? a))
(graphify a)
[])
(if (or (set? b) (vector? b))
(graphify b)
[]))))
(partition 2 1 structure))
:default [structure]))
@bcbradley functions don't see their own let binding, but it will work if you change (fn [[a b]] ...)
to (fn f [[a b]] ...)
also, the (fn f [[a b]] ...)
version will have a name with f in it in a stack trace, which can make debugging a lot easier
so my code is full of (let [foo (fn this-does-foo [...] ...) ...])
just so that if foo blows up, I can easily see in the stack trace which function that is
i may be asking too much: but do you think you could suggest a different approach to this problem?
i'm trying to output a bunch of ordered pairs (as vectors) which form the edges of a graph
that case could be a multimethod
(defmulti f (fn [a b] [(type a) (type b)]))
(also, come up with a better name than "f")
so a couple of sets in a vector like [#{A B} #{C D}] would need to become [{A C] [A D] [B C] [B D]] for instance
Basically vectors capture the idea of "sequentially" and sets capture the idea of "concurrently"
@bcbradley the way I would usually represent that is an adjacency list, which tends to be more usable in code - so your [[A C] [A D] [B C] [B D]]
would instead be {A #{C D} B #{C D}}
it contains all the same info, but associatively
thats not a terrible approach but i'm concerned about how it scales when you get lots of depth
adjacency lists are always shallow
i'm making a graphics engine for clojure, and at times its necessary to define a highly complicated order of draw calls
you might need to loop more times to get to your bottom, but the data stays shallow
where you "don't care" about the order of a set of draw calls, but do care about the order of sets of sets
right, that works with vals being sets (everything A depends on is "equal" at that level)
adjacency lists can represent arbitrary graphs, even if they have loops etc.
walking the graph becomes a bunch of cheap hash lookups
instead of linear walks across inputs
oh well i spent a couple hours making this complicated rats nest of a function for nothing lol
@noisesmith offtopic, did you release "record-as-a-function" lib/snippet yet? hi
@misha I got to a point that wasn't satisfying, I have code on github but it's far from ready
np - glad I can help
@noisesmith did it turned out to be harder than you thought? or is it "presentation" issue?
I got to a point where I realized I needed to make some hard design decisions, or I would end up with a mess
so I'm doing the design work (which doesn't always look directly like work, haha, ....)
hammock driven development for the win
but it is in progress and will end up here as it progresses - the current code is likely to be replaced entirely https://github.com/noisesmith/fixing-to
@noisesmith I want to merge FSM with an emit!
function, and it reminded me of your idea
simply to avoid passing machine around everywhere where I need to emit events. But, on the second thought, I'd need to pass around that emit-containing-machine function anyway, so it might not be worth it
hrm on second thought i'm not sure using an adjacency graph is ideal-- it does make lookups faster, but my use case involves converting a large amount of data into a dependency graph, which is then converted into a sequence that can be conveyed into opengl commands-- in other words its just one big batch and I don't really need to use it as a look up map
what repetition? what's redundant there?
I thought your example indicated both A and B had direct dependences to both C and D
so that info isn't redundant (if that's the case) and if that's not the case, that wasn't the right translation
basically if i have something like [#{A0 A1 A2 A3 .. AN} #{B0 B1 B2 B3 ... BM}], the adjacency graph will have N repeated instances of #{B0 B1 B2 B3 ... BM}
adjacency is considered way more compact than a dependency matrix. if you have sparse data then adjacency is for sure the way to go
because this is the top level abstraction, i'd like to be able to just change a given draw call in one place rather than in N places
if the concern is size, you can give #{BO ... BM} a name, or even index it as a key to another map
yeah the name idea was my first thought but it doesn't really jive well with what i had planned
i wanted to be able to literally define a draw pipeline as a data structure, with no let or special forms
i'm just afraid that if I do an adjacency map it will blow up the .edn file (not a terribly big issue) and that it would be a pain to change any specific draw call (because it is repeated a bunch of times in a bunch of structures)
thats the reason I had to think up a way to communicate what is basically a DAG without repeating any node
and the best i could think up was attaching semantics to vectors and sets (sequentially and concurrently respectively), with arbitrary nesting
you could introduce "pseudo-nodes" representing shared dependencies but not carrying any domain meaning
it should be straightforward to write code that parses them out when using the data
eg. you start with a->c a->d b->c b->d and end up with a->A b->A A->c A->d
maybe that's weird, but it preserves dep order and reduces link count if used properly
that isn't a bad idea but if i'm not mistaken writing an algorithm to optimally reduce the link count to its minimum would be tantamount to the algorithm i had already written
in fact if you think about it, i suppose there may be many ways to present the interconnectedness of a DAG while not repeating yourself-- you could either simply not repeat yourself, or you could repeat yourself but make it less painful by only repeating small names like 'A' in the example you just gave with "pseudo nodes"
i guess what i'm trying to do really is super recursive so my function is ugly because it has to be ugly
well, like I initially said, f
would be a lot nicer as a multimethod
why are you nesting concat directly inside concat anyway?
(concat a (concat b c)) can always be replaced with (concat a b c)
i think at some point i had a cond in between them but didn't think about simplifying when i removed it
also (if p? a []) inside a concat context can be safely replaced with (when p? a)
since concat acts on [] and nil identically
also, mapcat inside concat is suspicous - not that it's never needed, but it makes me wonder
err, concat inside mapcat this is, of course
basically the rules for "do these concurrently" and "do these sequentially" don't imply that "these" have to be draw calls
i guess i've probably spammed my problem enough though, cheers and thank you for helping me
Ideally, I would like to start a REPL that has the same settings as the one it’s launched from :thinking_face:
via jreadline? maybe what you want is to make another nrepl connection to your existing one
I want something like https://github.com/razum2um/clj-debugger, i.e. a way to start a REPL at a breakpoint with all local variables etc
is there a way to reload a JAR you’ve modified with lein install
in a REPL, without closing the REPL?
you can reload the files by file path
that's what editors do
you can't reload the jar itself if the deps are already provided
there's no good way to replace some class that is already in the classpath in clojure - (except built in things like defprotocol and defrecord that are actually making a new class with the same name that replaces the old one on future lookups)
I'm not sure where the limit is, but people have a lot of reason to want that to work and it doesn't so far
but you can re-load the source files without loading the new jar, and that works
but it's easier to do that from the file path rather than the jar, using load-file
that's the typical repl friendly workflow (whether done explicitly, or under the hood when you tell an editor to reload an ns)
I have a macro that lets me minimally describe the file name, and it finds the file based on the project naming and location conventions in my directories
so that (le foo bar)
turns into (load-file "/home/justin/clojure/foo/src/foo/bar.clj")