This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-03-24
Channels
- # announcements (10)
- # aws-lambda (9)
- # babashka (14)
- # beginners (166)
- # calva (63)
- # chlorine-clover (4)
- # cider (40)
- # cljs-dev (4)
- # clojure (182)
- # clojure-europe (18)
- # clojure-italy (5)
- # clojure-nl (5)
- # clojure-spec (17)
- # clojure-uk (55)
- # clojurescript (11)
- # core-async (12)
- # cursive (23)
- # datascript (5)
- # datomic (19)
- # emacs (4)
- # fulcro (46)
- # graalvm (2)
- # hoplon (2)
- # joker (3)
- # juxt (1)
- # keechma (2)
- # leiningen (20)
- # malli (1)
- # meander (7)
- # nrepl (1)
- # off-topic (72)
- # pedestal (6)
- # re-frame (15)
- # reitit (7)
- # shadow-cljs (34)
- # sql (14)
- # testing (14)
- # tools-deps (11)
- # tree-sitter (1)
- # vim (14)
- # xtdb (19)
- # yada (3)
@glfinn83 If you are going with defprotocol, check out shrubbery. https://github.com/bguthrie/shrubbery
@hindol.adhya Awesome, thanks!
Hello, did anyone read https://luminusweb.com/docs/guestbook documentation and book asociated with it? Is book worth buying? is it a lot different than documentation?
Yes it's a very good book, the most comprehensive one on Clojure web development I know of. And I'd say more generally applicable than the Luminus docs because people tend to pick and choose libraries in practice.
hi, I see some code in libraries with the notation of (defn foo* [x] (..)) (defn foo [x] (foo* x))
Is there any convention with *
? couldn't find anything on the clojure-style-guide
nothing strong, sometimes a pattern used to separate a public fn and a helper impl fn
inside clojure core, trailing * often actually marks a special form implementation that is implemente by the compiler, but that's a special case
I think of it as similar to foo'(x)
in the math tradition, but we can't use the ' character in clojure, so we use *
well, you can use ' in clojure
foo' is a perfectly good symbol name
you can't put it in the front of course :)
I revise my statement to "I'm scared to"
no fear needed, it's used all over
and officially in the docs as a valid constituent character https://clojure.org/reference/reader#_symbols
yes, sorry for the misinfo. Will be more careful with my words moving forward 🙂
Anyone here use com.novemberain/langohr for RabbitMQ? After adding it to my project I get these annoying messages (it can't find SL4J conf in classpath):
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See for further details.
That is using http://slf4j.org logging facade and it is complaining about missing logging implementation. To fix this you’ll need to include depency that includes the dependency
The linked page has instructions,
If you are responsible for packaging an application and do not care about logging, then placing slf4j-nop.jar on the class path of your application will get rid of this warning message.
I actually was oblivious to what SLF4J was, I thought this was a logging library, as this is an abstraction layer I'm more comfortable with this
The purpose of SLF4J is to give you the power to choose the right implementation for your app yet capture the logs from the library you pulled.
Without an implementation in path, it cannot log anything. But for any app in production, you will want to at least capture WARN and ERROR from every library you pull.
Do you know if it is just a Cider issue or not? I've had the same error and just added the slf4j library to my lein config
wondering, what dependencies do you have in your project? There might be a conflict here maybe
I actually got the error while playing around with clj-kondo
yesterday, but I think that there is maybe something up with my personal config, which relies on
:dependencies [[alembic "0.3.2"]
[com.gfredericks/dot-slash-2 "0.1.5"]]
:plugins [[lein-ancient "0.6.15"]
[lein-ubersource "0.1.1"]
[com.billpiel/sayid "0.0.18"]]
@mitchell_clojure @glfinn83 althought it is annoying, it's the default message. many libraries uses SLF4J abstraction to log messages. It's up to the users of those particular libraries to choose one of many SLF4J logger implementation. It's a great feature because most of the time, we already have a logger implementation in our running app and we don't have to worry about conflict with another libraries that brings another logger implementation.
I'm using Timbre, which is not going to help me here. I'm also to stubborn to add a dependency just for this lol
Yet another dependency I don't want though. Going to see if I can find something instead of Langohr
I don't think you need to be using it, you can just ignore the message, right?
lol, well I think there are ways to suppress the warning with your user profile
how to download username, password and anti forgery token based website using clojure? i have used clj-http. Can anyone show me a way to do this? i am kind of noob in this.
@U010FU3Q9N0 don't know how to do that. Can you please elaborate or enlighten me about this?
I can just tell you that I am just a noob in web development,and I found ring-clojure is a simple,good framework.Yo You can search it on github
So I am prompting a user (at the command-line) to input a number. If a number is not input I just want to "loop" back around and prompt again until a number is entered. Is this what I would use try/catch
for? I basically read in the input as a string using (read-line)
right. Then do something like (try (Long/parseLong n) (catch Exception e)
... or what? and then how do I circle back to the prompt?
read-line and the prompt share the same input, it's automatic
if you don't readline in another thread, it won't interfer
@U9J50BY4C This might be a good use case for trampoline
.
I don't see how trampoline would help
(defn get-num []
(println "Number: "
(let [num (read-line)]
(try
(Long/parseLong num)
(catch Exception e)))))
But I don't actually know how to do this. I'm reading clojuredocs but could use a more extensive resource on try/catch if you folks have it.
Yeah, once the user inputs a valid number the program runs some calculations and that's that. Nothing crazy going on here.
@U051SS2EU To repeatedly execute read till a number is found.
EDIT: But recur
can do that as well.
Yup. Ok. Seems obvious now that I think of it. Lol. But I would still like to learn more about exceptions and error handling all that jazz if anyone has Clojure resources on that.
I'm not experienced enough with Clojure to say much about exceptions, but I would search for articles on idiomatic error handling. My guess is that their primary purpose is for integration with Java/JS code and not to be used more generally
@UVDD67FFX In the JVM world, exceptions are the canonical way to handle exceptional cases. try/catch
is not unidiomatic.
so now when I use this:
(defn get-num []
(println "Number: "
(let [num (read-line)]
(if (number? (Long/parseLong num))
(valid-cc? num)
(get-num)))))
it doesn't print out "Number: " first. It just sits there waiting for the input with no prompt. and then afterwards does "Number: nil" after my other calculations do there thing.
you might need to add a call to (flush)
@hindol.adhya In Java world, definitely. You wouldn't typically use exceptions in Scala
@U9J50BY4C the problem is the entire body is inside the println
ok. Also if it isn't a number it gives me the NumberFormatException and terminates instead of calling the function again
you need to take the let out of the println
@UVDD67FFX In Clojure though, it is not frowned upon or anything.
@U9J50BY4C right, that's where you do the try/catch and return nil
@hindol.adhya thanks, that's interesting.
So then I can't just use the predicate? Which takes me back to the syntax of using the try/catch.
like this
(ins)user=> (try (Long/parseLong nil) (catch Exception _))
nil
(ins)user=> (try (Long/parseLong "1") (catch Exception _))
1
wrap the smallest possible block in the try
then have a conditional on whether the return was nil
or use some->
hmmm. Ok. Seems to be getting a bit difficult to just see if the input is a number or not and loop back around.
one moment I'll have an example
(cmd)user=> (load-file "/tmp/get-num.clj")
#'user/get-num
(cmd)user=> (get-num)
(cmd)Number: alsdjf
(ins)Number: ajdsfk
(ins)Number: lllll
(ins)Number: 3
3
(defn get-num []
(print "Number: ")
(flush)
(let [input (read-line)
num (try
(Long/parseLong input)
(catch Exception _))]
(if num
num
(recur))))
that last line should probably be (or num (recur))
but that expands to the same thing anyway
Ahhh! Very informative. So you are saying the try
will return nil
if it is not a number which evaluates as false in the if statement?
try returns the body of the catch if it is invoked, here the catch implicitly returns nil as there's no body
you could make it explicit by adding false or nil to the catch
and yes, clojure treats nil as false in conditionals
it means you can get input on the same line as the prompt
it flushes partial output (newline automatically gets flushed)
here's an alternate version (does the same thing, may or may not be clearer)
(defn get-num []
(print "Number: ")
(flush)
(or (try (Long/parseLong (read-line))
(catch Exception _
false))
(recur)))
also, I've seen (defn safe-long [s] (try (Long/parseLong s) (catch Exception _)))
in multiple code bases, sometimes I write it, sometimes someone else does
It is also possible to use clojure.edn/read-string
and check if the resulting thing is a number?
, int?
or integer?
depending on what you want. That avoids the try/catch
as well.
but it will still throw on eg. ")"
I don't like using read-string for user input
lojure 1.10.1
(cmd)user=> (read-string ")")
Execution error at user/eval1 (REPL:1).
Unmatched delimiter: )
(ins)user=> (read-string "#=(java.lang.System/exit 1)")
justin.smith@C02ZW014LVDN ~ %
that is, #= is read-eval, and it does things you probably don't want
oh, I missed that you specified clojure.edn
hello all. I´m writing a macro like this
(defmacro with-browser
[browser & body]
`(let [browser# ~browser]
(try
~@body
(finally
(quit browser#)))))
something like should work:
user> (defmacro with-browser [[symbol obj] & body]
`(let [browser# ~obj
~symbol browser#]
(try
~@body
(finally
(quit browser#)))))
also macroexpand
is your friend here:
user> (macroexpand '(with-browser [browser (create-driver)]
(println browser)))
(let*
[browser__5732__auto__
(create-driver)
browser
browser__5732__auto__]
(try (println browser) (finally (user/quit browser__5732__auto__))))
user>
It's an open invitation to ask a question if you have one =)
if you got a bit of time on your hand, i am wondering how to get sums of repeating keywords in a nested map. For instance if i have a map: {:a 1 :c { :a 2}} how do write a function (f map :a) -> 3
imagine the nested map has multiple levels and i am only interested in summing the values of a certain keyword that might be repeating at different nested level of the map, could also be in a vector
user=> (->> (tree-seq coll? seq {:a 1 :c { :a 2}}) (filter map-entry?) (filter (comp #{:a} key)) (map val) (apply +))
3
I think this one is better, does the same thing
user=> (->> (tree-seq coll? seq {:a 1 :c { :a 2}}) (filter map?) (keep :a) (apply +))
3
wow thanks, that works great! my postwalk involved atoms to track a counter but now i see that theres a much simpler way
tree-seq is great for when I want to process my tree as if it were a graph :D
that is, if only data types / keys are significant, and not the relative layer in the nest
It's an open invitation to ask a question if you have one =)
In Clojure.spec, does gen/fmap
and gen/let
achieve the same functionality? What would be the difference?
I am not completely sure how it applies, but in general in functional programming, fmap
indicates an operation that applies a pure function to a value in a context. So fmap
allows you to apply a function that evaluates a value coming from a generator to create a new value.
From what I can see, gen/let
allows you to evaluate a value coming from a generator to create a new generator.
In other languages, this would make let
strictly more expressive.
But this is my ‘general’ functional programming experience speaking
Take a look at gen/bind
, to which gen/let
expands
(Hope this helps!)
Thanks a lot!!
Hi! I've got one for you: I have a map with keys/vals like this: {id int title string done bool template string} I have a string for a given template (ex. "Bob", and a list that contains strings (ex. (list "Thing1" "Thing2" "Thing3"). I want to autoincrement the id and add entries to the map iteratively until the list of strings runs out, such that I have something that looks like this: { {:id 1 :title "Thing1" :done false :template "Bob"} {:id 2 :title "Thing2" :done false :template "Bob"} {:id 3 :title "Thing3" :done false :template "Bob"} } I've been having a heck of a time figuring out this seemingly simple task in Clojure. Please help!
where ... is your boilerplate keys and vals of course
Or (map #(assoc {...} :id %1 :title %2) (range) things)
aha! I'll give this a try, thanks
I need it spelled out, if you don't mind. What is ... referring to? The existing map name? Or is {...} some symbol I'm not familiar with yet?
... is the keys and vals that don't change
(map-indexed (fn [i title] {:id i :title title :done false :template "BoB"})
things)
it was just a shorthand so I wouldn't have to do as much typing
Sorry man. 🙂 Thanks for the details.
Does anybody have experience using amazonica
?
At this point I can't even load it into the repl because somehow the amazonica.core
ns isn't available
you can just directly ask questions, but yes
Whenever I switch to a ns that requires amazonica.aws.s3
I cannot eval the ns definition because core isn't available
what happens if you try (require 'amazonica.core :reload)
(fixed typo)
that should show you whatever error is preventing it from being available
(or fix the issue, slim chance)
It reads
Syntax error (NoClassDefFoundError) compiling def at (core.clj:221:1).
Could not initialize class com.amazonaws.ClientConfiguration
I am wagering that is related to my auth config
what is the full printout of *e
oh wow, I didn't know about that
it seems strange that it would initialize auth while loading an ns
#error {
:cause "Could not initialize class com.amazonaws.ClientConfiguration"
I guess it's a weird library
@brandon149 most people just skim it as if it was spam, but the startup message of most repls do mention *e
@brandon149 I really did mean the full content, not just the message
(you can put it as an attachment so it's less spammy)
this looks like it might be relevant - missing dep on your classpath? https://stackoverflow.com/questions/39641202/java-lang-noclassdeffounderror-could-not-initialize-class-com-amazonaws-clientc
or a version that doesn't play nicely
another instance of the same message with a potential fix https://github.com/databricks/spark-redshift/issues/133#issuecomment-164825253
maybe check lein deps :tree
for jackson verison conflicts, jackson very frequently makes things break