This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-22
Channels
- # announcements (8)
- # babashka (4)
- # beginners (164)
- # calva (17)
- # cider (30)
- # cljdoc (4)
- # cljs-dev (6)
- # clojure (103)
- # clojure-europe (63)
- # clojure-nl (1)
- # clojure-norway (1)
- # clojure-portugal (1)
- # clojure-uk (3)
- # clojured (10)
- # clojuredesign-podcast (2)
- # clojurescript (16)
- # conjure (2)
- # core-async (9)
- # cursive (26)
- # datalevin (4)
- # datomic (156)
- # gratitude (1)
- # holy-lambda (8)
- # honeysql (9)
- # hoplon (6)
- # off-topic (55)
- # polylith (14)
- # portal (21)
- # reagent (5)
- # reitit (16)
- # releases (3)
- # shadow-cljs (87)
- # spacemacs (3)
- # tools-deps (25)
- # xtdb (9)
There's some relationship between them. In Joy of Clojure, they used it build a variant of lazy seqs: https://github.com/jumarko/clojure-experiments/blob/master/src/clojure_experiments/books/joy_of_clojure/ch06.clj#L291-L329
a big difference is you can print a delay without forcing it.
Hello, how do I give my map argument to a function like so
(defn mk-pool
[& {:keys [cpu-count]}]
cpu-count))
(mk-pool {:cpu-count 5})
doesn't seem to workWhat version of clojure are you using? I think that syntax was added in 1.11.
You use the following syntax with any version any version 1.2.0 or later:
(mk-pool :cpu-count 2)
I want to make a thunk out of a function call w/ some args. (partial my-fn arg1 arg2)
works, but makes it look like I'm expecting more args to be added... Should I care? Is there a nicer way to do it?
#(my-fn arg1 arg2)
as a possible alternative, but personally I wouldn't care
Ah, thanks! And of course! I tend to avoid #()
so it was out of my mental reach. 😃 I think I prefer #()
over partial
here, b/c the reasons in OP.
If you do it more than once, it warrants making a macro out of it. I like using $ for it:
(defmacro $ [& body] `(fn ~'thunk [] ~@body))
(($ (str 'foo 'bar)))
"foobar"
Very nice! Is it possible to get the function name in there as well? So that instead of
($ (str 'foo 'bar))
#function[user/eval63202/thunk--63203]
We would get
($ (str 'foo 'bar))
#function[user/eval63202/str-thunk--63203]
Not as simple, but sure:
(defmacro $ [& body]
(let [name (or (and (sequential? (first body))
(symbol? (ffirst body))
(-> body ffirst name (str "-thunk") symbol))
'thunk)]
`(fn ~name [] ~@body)))
($ (str "foo" "bar"))
I'm using a third party library and don't want to unit test it, so am using a ”command”-ish approach where I have different implementations for :test
and for :prod
(I'm using multimethods for it). For tests I don't want to write a lot of different implementations so have made just one that expects a thunk.
I seem to have shot myself in the foot pretty good - I am unable to start my cider repl due to a class not found exception being encountered after adding both muuntaja
and cheshire
to my lein project at the same time. Looking at the trace it appears that the error is coming from something in muuntaja
. I presume this is because these two libraries maybe have conflicting versions of dependencies on the classpath. I am able to get going again if I remove my cheshire
dependency. How would I resolve something like this without removing the dependency? Also, how can I prevent getting into this situation in the first place?
I ran lein deps :tree-data
and there are a lot of suggestions on exclusions. It is a pretty large dependency tree so maybe that is expected.
Generally, exclusions tell the dependency resolver to not include a particular dependency of an artifact (because a different but hopefully compatible version will be included in a different artifact).
Is there a common idiom for the following or
?
(defn candy? [x]
(or (= x :butterfinger)
(= x :snickers)
(= x :zagnut)))
Sets are functions, if you pass an element it contains you get the element back, otherwise nil
you could use a set: (contains? #{:snick :bf :zag} x)
Isn't it more idiomatic to just use set as function?
(#{:butterfinger :snickers :zagnut} :zagnut)
=> :zagnut
(#{:butterfinger :snickers :zagnut} :nut)
=> nil
You can, but predicates should return true/false. You could also use (boolean (#{:b :s :z} x))
but I personally like the clarity of using contains?
YMMV
That’s better!
How could I go about setting the MathContext for my whole application? Would something like this be truly global, including multiple threads? Is there a more idiomatic way of doing this?
(alter-var-root #'*math-context* (constantly (MathContext. 5 RoundingMode/HALF_EVEN)))
Did you try (set! *math-context* <some-desired-value>)
?
Yes I did, it works on the repl but not on the built app. Can't change/establish root binding of: *math-context* with set
> Currently, it is an error to attempt to set the root binding of a var using set!, i.e. var assignments are thread-local. In all cases the value of expr is returned. https://clojure.org/reference/vars
If you don't start your app using clojure.main, the bindings won't be setup. Are you starting the app using a gen-class AOT?
In that case, you need to bind them in your main function:
(defn -main [& args]
(binding [*math-context* *math-context*]
;; Now using (set! *math-context* ...) will work
...))
You can also just use this: https://clojuredocs.org/clojure.main/with-bindings So wrap your -main body in that macro
(ns foo
(:require [clojure.main :as m]))
(defn -main [& args]
(m/with-bindings
;; Now using (set! *math-context* ...) will work
...))
That said, normally those bindings are compile time options. I'm not sure about *math-context*
, but my guess is it is as well.
That means, if you want to set those globally, you can do it in the compilation itself.
For example if you use tools.build: https://clojure.github.io/tools.build/clojure.tools.build.api.html#var-compile-clj
You can use :bindings
on the compile-clj step.
How do i connect to clj repl. I started clj repl with clj -A:dev (dev alias has only extra path for /dev folder that has user.clj file) but when i try to cider-connect to localhost i get a message
nrepl Dirrect connection to localhost:36603 failed
Does anyone know why is that?
I can cider connect to repl when i start it with lein repl
Usually, the easiest way to start a repl and connect with cider is cider-jack-in
clj -A:dev
starts a repl, but cider-connect
expects an nrepl
If you'd like to start the nrepl yourself, https://nrepl.org/nrepl/usage/server.html
oohhh ok that's great information.
Maybe i am approaching this in a wrong way then.
So i would like to cider-jack-in
and i would like to do (start)
which is in dev/user.clj
At the moment when i cider jack in i have to evaluate user namespace and then i can (start)
What does (start)
do?
Unfortunately, I'm not sure what the best way to run a command on cider-jack-in
in emacs. You could also ask in #emacs.
I'm probably running an old version of cider and emacs. I set a the variable cider-clojure-cli-parameters
to "-M:dev:project -m nrepl.cmdline --middleware '%s'"
so that I can add extra aliases.
I also don't really use user.clj
I would usually just run it manually I guess
You could also try adding a defadvice
to your cider-jack-in
command to run it, but I'm not really sure what the best way is since that's not something I usually do
in your deps.edn
dev
alias you could add something like this:
{:extra-deps {cider/cider-nrepl {:mvn/version "0.28.3"}}
:main-opts ["-m" "nrepl.cmdline" "--middleware"
"[cider.nrepl/cider-middleware,refactor-nrepl.middleware/wrap-refactor]"
"-e" "\"(mount.core/start)\""]}
that way running clj -A:dev
will run an nrepl and execute mount.core/start
, then you can cider-connect-clj
to it.
This works, this is basically the comment cider jack in uses to initiate te repl.
When i cider-connect
i can use (start) right away without the need to evaluate the namespace.
So what exactly prevents plain cider jack in on loading namespace ?
this is my dev
alias now
{:extra-paths ["dev"]
:extra-deps {cider/cider-nrepl {:mvn/version "0.25.1"}}
:main-opts ["-m" "nrepl.cmdline" "--middleware" "[cider.nrepl/cider-middleware]"]}
I think cider-jack-in
might override some of that
If you do C-u M-x cider-jack-in
it should show you the full command it uses (and allow you to edit it)
I think there are some variables you can customize to tweak the command it uses though
I thought i shared it...
/usr/local/bin/clojure -Sdeps '{:deps {nrepl {:mvn/version "0.7.0"} cider/cider-nrepl {:mvn/version "0.25.1"}}}' -m nrepl.cmdline --middleware '["cider.nrepl/cider-middleware"]'
It's 1:1It doesn't look like it's using the dev alias
true it seems that this might help https://docs.cider.mx/cider/basics/up_and_running.html#clojure-cli-options I will check it out and report back Thank you both for your time
You can do also do M-x customize-group
and check all of the groups that start with cider
A .dir-locals.el file that defines the Clojure CLI aliases to include when running a REPL is a simple approach https://clojurians.slack.com/archives/C0617A8PQ/p1650665847187939?thread_ts=1650655838.638489&cid=C0617A8PQ
Unfortunately, I'm not sure what the best way to run a command on cider-jack-in
in emacs. You could also ask in #emacs.
If I'm in a namespace and define a spec with s/def - can I import that spec from a different namespace? I don't actually see the spec when I'm browsing my namespace in cider
specs are just named with their keyword, so you can just use it from another namespace
you do need to ensure the spec has been loaded into the registry though, so you'll need to ensure the namespace has been require
d before use
VS-Code/Calva: I just figured out (well almost) how to run jetty inside the repl.
But now I want to stop jetty and continue using the repl.
So I tried ctrl-c, ctrl-d, ctrl-c twice, ctrl-c ctrl-q
at the repl but to no avail.
ps: (jetty/run-jetty #'app {:port 4000})
is how I’m running jetty.
Add :join false
to the hash-map that is passed to the jetty/run-jetty function to return control to the REPL prompt after jetty starts
https://practical.li/clojure-web-services/app-servers/atom-based-restart.html
It wasn’t about the :join flag
. I thought the jetty process was running as a REPL child process. So I tried to CTRL-C the jetty process at the REPL 🙂 now I understand that it’s running in the vs code terminal.
ah that must be the “join” flag. I remember seeing it on some blog. but anyway how do get it to shutdown without having to restart vscode? I guess that’s more of a vscode / calva problem….
You need to stop your repl from the terminal it’s running in, which is not the Calva repl window in the right pane in your screenshot. In the terminal where the repl is running, hit ctrl+c.
But as was stated already, to prevent needing to do that again you’ll need to use the join flag.
Still trying to fully grok lazy-seq here. Something I'm confused about is in the docs (https://clojuredocs.org/clojure.core/lazy-seq) they commonly have (lazy-seq (cons a (lazy-seq etc))), the question is, the documentation for cons is not lazy (https://clojuredocs.org/clojure.core/cons), thus cons would attempt to resolve the lazy-seq for the first time, causing infinite loops and what-not.
according to https://stackoverflow.com/questions/12389303/clojure-cons-vs-conj-with-lazy-seq it sounds like cons is actually lazy even though the docs don't mention it.
A call to the lazy-seq macro suspends everything inside it until the seq is being realized
Usually calls to cons are wrapped in calls to lazy-seq which is what makes a lazy seq
I feel pretty confident I know more about clojure internals than the majority of people answering clojure stackoverflow questions
lazy seq is a lazy seq, list is a list, you can't make a real value and pre-pend it to a lazy seq
but if you read how its implemented, or at least his description of it, that is not what it does?
I mean like what would you do, in the case of a cons being somewhere inside of a lazy-seq, selectively create another lazy-seq which then transfers to another lazy-seq
I'm not arguing to argue, I'm trying to correct myself by explaining it the way I understand it
Like, you can see that cons is not lazy, if you type (do (cons (println 1) (println 2)) nil)
And you won't get an error because println returns nil, so you are effectively calling (cons nil nil)
where nil is taken to mean the empty seq, so that cons call makes a seq which is not lazy, that is has a single value, nil
in that case that you describe, (println 2) is evaluated of course, but if it was a (lazy-seq) it evaluates into lazy evaluated body etc...
I suppose what the disconnect is, is that lazy-seq can have both lazy and real elements in it
Seq is just a Java interface right, it can have many different implementations that do whatever
So the lazy-seq seq forces its delay(more or less) when you call first or rest on it, which produces the non-lazy seq made via cons, and the lazy-seq forwards the first or rest call to the non-lazy seq
Perhaps this is more compelling evidence?
dev=> (take 1 (cons (println 1) (lazy-seq (cons (println 2) (println 3)))))
1
(nil)
dev=> (take 2 (cons (println 1) (lazy-seq (cons (println 2) (println 3)))))
1
(2
3
nil nil)
And, in modified form, if you extend it:
dev=> (take 2 (cons (println 1) (lazy-seq (cons (println 2) (lazy-seq (cons (println 3) []))))))
1
(2
nil nil)
dev=> (take 3 (cons (println 1) (lazy-seq (cons (println 2) (lazy-seq (cons (println 3) []))))))
1
(2
nil 3
nil nil)
(in particular, compare the two different take 2
versions)
Seqs are really linked lists, but just lifted to an interface instead of a concrete cons cell representation as in older lisps
It can be particularly confusing when you interact with other "lazy" functions that operate on chunked sequences because you'll get blocks of 32 items at a time, even if you only ask for a dozen items...
And the interface allows you to do things like lazy seqs (delays) or custom seqs for iterating over collection types (like most clojure collections have)
(but that's just an efficiency artifact of "lazy sequences" rather than lazy-seq
)
And, yeah, @U0NCTKEV8 is a pretty definitive source of correctness about Clojure internals 🙂
two examples that i think can help explain:
(def l (cons :a (cons :b (cons :c (cons :d (range 1e6))))))
is l completely lazy or completely realized? it wouldn't make sense to make the cons lazy when we have concrete values a, b, c, d, etc. Cons isn't lazy there
oh and I'm definitely not, I'm just trying to get a more thorough understanding of it all
and (def l (concat (range 1e6) [:a :b :c :d] (range 1e6)))
a "lazy" portion with a million elements, then a clearly realized portion with 4 elements, and then a lazy million element portion again
but each individual linked list node itself being a totally arbitrary way to point to the next element in a linked list cell is so very much OOP that its probably right
It's why we use vectors in Clojure a lot. They can behave like sequences but are much more efficient in a lot of situations.
While all three of these behave like sequences of 1, 2, 3, they are different types:
dev=> (type (list 1 2 3))
clojure.lang.PersistentList
dev=> (type (cons 1 (cons 2 (cons 3 ()))))
clojure.lang.Cons
dev=> (type [1 2 3])
clojure.lang.PersistentVector
dev=> (type (range 1 4))
clojure.lang.LongRange
As in:
dev=> (range 1 4)
(1 2 3)
dev=> (seq [1 2 3])
(1 2 3)
dev=> (cons 1 (cons 2 (cons 3 ())))
(1 2 3)
dev=> (list 1 2 3)
(1 2 3)
I have no idea if boxes-for-Java-objects-in-memory and arrows-for-pointers/references pictures of Clojure lazy sequences being realized one element at a time would be at all useful to you, but there is a library I wrote called cljol
with a gallery of images I produced using that library, showing such pictures, with some associated text attempting to describe what is happening: https://github.com/jafingerhut/cljol/blob/master/doc/README-gallery.md