This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-17
Channels
- # announcements (3)
- # babashka (41)
- # beginners (118)
- # calva (4)
- # cider (22)
- # clj-kondo (4)
- # clj-on-windows (1)
- # cljtogether (1)
- # clojure (164)
- # clojure-europe (46)
- # clojure-filipino (1)
- # clojure-indonesia (1)
- # clojure-my (1)
- # clojure-nl (3)
- # clojure-sg (1)
- # clojure-spec (13)
- # clojure-uk (16)
- # clojurescript (18)
- # cloverage (3)
- # conjure (5)
- # core-async (8)
- # cursive (21)
- # datomic (4)
- # deps-new (15)
- # emacs (12)
- # expound (4)
- # fulcro (45)
- # graalvm (32)
- # jobs (1)
- # malli (5)
- # nextjournal (63)
- # off-topic (27)
- # other-languages (3)
- # pathom (27)
- # proletarian (1)
- # rdf (24)
- # re-frame (10)
- # reagent (9)
- # releases (2)
- # shadow-cljs (72)
- # spacemacs (4)
- # timbre (4)
- # tools-deps (29)
- # xtdb (4)
Does anyone know the historical reason some
returns true
or nil
instead of true
or false
? Is there a similar function that only returns a boolean value?
Thank you for clearing that up. What is the canonical way to test if any of the values in a collection (mainly a vector or list) match my pred?
if you really need booleans instead of truthy/falsey you can use (comp boolean some)
but most things in clojure (if, or, and, etc) are fine with nil and false as false and everything else as true
often the only times i care about true booleans is i’m grouping by a predicate and then i need true
or false
. (let [{missing false valid true} (group-by pred coll)] ...)
. Most other times truthy and nil punning are just fine
Ok, great. Thank you. I was worried that Clojure was stricter about the nil/false distinction.
I use the slf4j in deps.end
:deps{org.slf4j/slf4j-api {:mvn/version "1.7.36"}}
user=> (require '[clojure.tools.logging])
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See for further details.
how can I bind the logger implementation?@imxingquan You've specified the API (good) but you also need to specify an implementation: slf4j-simple is probably what you want. There's also slf4j-nop (for no logging) and several others (including bridges for other logging libraries)
(Java logging is a giant mess!)
This may help https://lambdaisland.com/blog/2020-06-12-logging-in-clojure-making-sense-of-the-mess (or it may confuse further). At work, we've decided to use log4j2 but that has its own peculiarities as far as getting it all set up with deps.edn
etc.
This is a guess, but many things that aren’t your shell don’t interpret ~
- could you try with a full path?
I forgot reference ch.qos.logback/logback-classic {:mvn/version "1.2.10"}
in deps.edn
I use the project/jar, show error
$ clojure -X:project/jar :main-calss myapp.core
$ java -jar project.jar
no main manifest attribute, in project.jar
Because :main-calss
should be :main-class
on that first line?
Also make sure your myapp.core
's ns
form contains (:gen-class)
so that it will produce a Java-compatible class with your -main
function in it.
main code:
(ns bzsczx.core
(:gen-class))
(defn greet
"Callable entry point to the application."
[data]
(println (str "Hello, " (or (:name data) "World") "!")))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(greet {:name (first args)}))
$ clojure -X:project/jar :main-class bzsczx.core
:aot is not recommended for a 'thin' JAR!
Compiling bzsczx.core ...
Building thin jar: project.jar
Processing pom.xml for {net.clojars.bzsczx/taskphonecall {:mvn/version "0.1.0-SNAPSHOT"}}
$ java -jar project.jar
no main manifest attribute, in project.jar
Oh, you're building a library JAR. You need to build an uberjar for an application.
What is :project/jar
?
Ah, it's from https://github.com/practicalli/clojure-deps-edn yes? You want :project/uberjar
I build an uberjar use project/uberjar
. and java -jar uber.jar after show me
user >
not run main function immediately and enter the Clojure runtime
Sounds like you didn't specify :main-class
?
As :project/uberjar
is a user level alias, it's not going to know the specific main class name (which is different for each project).
Template tools that generate a Clojure project (clj-new or deps-new) may include the main-class value when a new project is generated, simplifying the alias use.
def
always creates a top-level (global) definition.
let
creates local bindings.
(and that Q seems to have nothing to do with the rest of this thread)
(def seq1 [1 2 3 4 3 4])
(let [col1 #{}]
(doseq [x seq1]
(conj col1 x))
(println col1))
;; I want this result col1{1 2 3 4}
;; pseudocode
var col1 = #{}
for (n in seq1){
if(n is not in col1){
add n to col1
}
}
The pseudocode up is the logic I want, but I don't know how to write it in ClojureTake a look at clojure.set/union
: https://clojuredocs.org/clojure.set/union
Other than than, in Clojure, collections are immutable. That means that this:
(doseq [x seq1]
(conj col1 x))
does not do what it does in imperative languages. It does not modify col1
to add x
into it. Instead, for each element in seq1
, it creates a copy of col1
with x
added, then throws the result away. doseq
is only for doing things that have side-effects.There is no reason to check if X is in col1, because col1 is a set. You cannot have duplicate values anyways
If what you want is a set of the unique values in seq1
(and a set will by definition only contain unique values) you can simply create a set from the seq1
collection. i.e.
(set seq1)
However, this won't have retained the order that the elements appear in in seq1
. For that you could use sorted-set
which takes each element as a separate argument so you need to apply it. i.e.
(apply sorted-set seq1)
To turn that back to a vector use vec
i.e. (vec (apply sorted-set seq1))
(set col1)
best represents your pseudo-code. But, you say you want the result 1 2 3 4
. If ordering matters, then you can use (distinct col1)
to get a sequence of all distinct elements in the order of first-appearance in the input-seq. (sort (set col1))
and (into (sorted-set) col1)
are both ways to get the distinct elements in their sorted order (sorted according to compare
).
I don't want from seq1 to set. I want to do something.
;; pseudocode
var col1 = set //memoize n
for (n in seq1){
if(n is not in col1){
add n to col1
do something !!
}else{
nothing to do!!
}
}
like this how to write in Clojure(def seq1 [1 2 2 3 4 1 3])
(let [col1 (atom #{})]
(doseq [x seq1]
(if-not (contains? @col1 x)
(do
(println "do something " x)
(reset! col1 (conj @col1 x)))
))
output:
do something 1
do something 2
do something 3
do something 4
all right? :)Is there a reason you use an atom for this? You could create this collection using reduce instead
(def seq1 [1 2 2 3 4 1 3])
(reduce (fn [coll elem]
(println "Do something" elem)
(if (some #(= elem %) coll) ;; Checks if element is already in list
coll
(conj coll elem))) [] seq1)
should solve it without atomsIn this case, it might be slightly better to use a set in the reduce rather than a vector. So
(def seq1 [1 2 2 3 4 1 3])
(reduce (fn [coll elem]
(println "Do something" elem)
(if (coll elem) ;; Checks if element is already in set
coll
(conj coll elem))) #{} seq1)
Some loops (those that accumulate something) can often be replaced by reduce
in a functional style.hi,
I wonder how you spec functions.
With simplified examples, I sometimes like to put valid?
at the input and output of the function like below. But this approach may cause some degree of performance issue, if I use extensibly, right?
(defn add-seven [x]
{:pre [(s/valid? int? x)]
:post [(s/valid? int? %)]}
(+ x 7))
Otherwise, I could write like this using fdef
.
(s/fdef add-eight
:args (s/cat :x int?)
:ret int?)
(defn add-eight [x]
(+ x 8))
But this fdef
block will only be checking when I turned the instrument on, as far as I know. Like below.
(require '[clojure.spec.test.alpha :as stest])
(stest/instrument `add-eight)
Honestly, this instrumentation is a bit cumbersome when I want my specs to check everything I write, as I have to write this (stest/instrument something)
line for every function with fdef?
I would like to learn what would be considered a good practice.You can call (stest/instrument) to instrument everything spec’ed
Or you can pass it a collection of symbols and use enumerate-namespace or other fns in stest to be more targeted if needed

Oh I didn't know I could (stest/instrument)
and all fdef
s are up. That's amazing.
Thanks!!
Same with unstrument too
Hello,
I am trying to implement auto-reconnect websocket logic (with fail safes so that i am reasonable user).
I am using atoms to hold the websocket client object which i later use for reconnects.
Sometimes i WS client might not even be created so i made a loop to attempt to create new connection and store it in atom.
My question is will i create memory leak or will WS client objects be properly garbage collected if i
(swap! connection assoc :socket (connect client url))
I realize that swap might be executed multiple times and that it should be used for pure functions but reconnect logic shouldn't happen often and i my thinking is if connections get garbage collected without being closed - all is well.
If my whole approach is backwards would you mind sharing resources how this could be done properly?
Thank you for your time
swap! potentially executing multiple times doesn't matter above. the final argument to swap!, the result of calling (connect …) is calculated only once.
Your clients/connections will be GCed when nothing hangs on to them. To prevent the map inside the atom from hanging on, when a connection breaks or closes, swap! dissoc it from the atom
@U050ECB92 thanks a lot, it makes sense.
Hello! When should I use defonce
instead of def
?
Below is a code snippet taken from shadow-electron-starter repo. defonce
is used. I’d like to know is def
ok here? What’s the difference between defonce
and def
?
(defonce state (atom 0))
(defn root-component []
[:div
[:button
{:on-click #(swap! state inc)}
(str "Clicked " @state " times")]])
reloading the namespace will not recreate the state var
Ah! Then when will the namespace be reloaded? I knew that editing code will cause hot reload during development, but can this happen in a running application? Or is it only a convenience for dev?
normally namespace won’t reload in production application, it is mainly used for repl-driven development, so that you don’t need to restart the entire app for code changes
Let's say I have a string like "the quick brown fox" and I want to replace all the spaces with hyphens... how can I do this in clojure?
there is a clojure.string namespace that wraps a lot of that stuff, but I tend to just call the methods on String
Ok. Is this better than using the "replace" function from clojure.core?
do you mean clojure.string/replace? b/c that has some nice affordances
(clojure.string/replace the-string " " "-")
?
but the replace in clojure.string is just because I habitually use the methods on String directly unless someone reminds me about clojure.string
One advantage is cross platform portability. This is especially important if you’re writing code in a library
in particular, the pattern/f-of-match arity can often be useful in clojure.string/replace
Ok thanks
What about if I want to delete certain characters from a string? Like if I want to turn "quick #brown !fox @ " into "quick-brown-fox" (I'm thinking about this in context of URLs)
Can I replace the characters with "" ? Or is there a better way to delete things? Thanks for the help guys
"better way" is extremely dependent, replacing with the empty string is likely to be good
How do I represent special characters? I'm thinking I will do (replace string "???" "")? What do I put for ???... do I put all the special characters I can think of, or is there a more succinct way?
Anything that should not show up in a URL
you can use a regex for grabbing multiple chars
but actually using a url-encode/decode is probably better for sure
Ok cool, I'll look more into that 🙂
Thank you
Ok a very beginner question... I found out that ring has a function ring.util.core/url-encode. I tried to use it in the repl with
(ring.util.codec/url-encode "this is my string")
But I get errors:
Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (URLClassLoader.java:433).
ring.util.codec
I also tried to require ring but I think I'm doing that wrong too
(require '[ring/ring-codec "1.2.0"])
Here's the error I get:
Execution error (ClassCastException) at user/eval2107 (REPL:1).
class java.lang.Character cannot be cast to class clojure.lang.Named (java.lang.Character is in module java.base of loader 'bootstrap'; clojure.lang.Named is in unnamed module of loader 'bootstrap')
What am I doing wrong here? I'm thinking it must be a syntax thing or I forgot a command?What's the correct way for me to require everything? 🙂
a library is a collection of code (clojure namespace, java classes, etc), when you launch you jvm process it needs all the libraries available at startup, so typically however you are launching that jvm process will need to be told what libraries you are using
[ring/ring-codec "1.2.0"]
is one way of specifying a maven coordinate, ring is the group id, ring-codec is the artifact-id, and "1.2.0" is the version of that artifacta maven coordinate is one of many ways you might specify to whatever tool you use that starts a jvm what libraries is should have available
So why doesn't
(require '[ring/ring-codec "1.2.0"])
work?Ohhhh I see. How do I do the namespace?
So do I need to add it to a project.clj file before just doing a repl out of the blue?
and the set of libraries available to that jvm is already set (not entirely true, but close enough)
Ohhhhhhhhh ok. Thanks! I'll try to add it to project.clj and then try again 🙂
once you have added it to you project.clj, then that library will be available to use, but you'll need to use require to load namespaces out of that library
Ok sweet thank you!