@rob370 did you check Exercism already? It’s both a community and command-line app that provides a learning experience along with a community-powered mentorship program
Oooh @joelwallis good recommendation
Exercism is awesome! I’ve even contributed to the JavaScript and the [now dead] ECMAScript track in the past. It’s really a master piece of self-learning platforms. I’ve been on it for JS, Elixir, Erlang, Python, Ruby, and other languages. Lots of fun is mostly guaranteed! 😆
@joelwallis there is an #exercism channel where people contributing to the Clojure track hang out
Awesome!!!
How can I make this code return strings rather than individual characters?
(let [car-names ["audi" "bmw" "fiat" "haval"]
car-models ["" ["x1" "i3"] "500" ""]]
(->> (map (fn [car-name car-model]
(cond
(= "" car-model) [car-name]
(coll? car-model) (map (fn [model] [car-name model]) car-model)
:else [car-name car-model]))
car-names car-models)
flatten))
;; => ("audi" "bmw" "x1" "bmw" "i3" "fiat" "500" "haval")
map would fit better for that case
(def cars {"Audi" []
"BMW" ["X1" "i3"]
"Fiat" ["500"]
"Haval" []})
=> #'user/cars
(for [brand (keys cars)
model (or (seq (cars brand)) [""])]
(str brand (when (seq model) " ") model))
=> ("Audi" "BMW X1" "BMW i3" "Fiat 500" "Haval")
alternative to looking up the keys is grabbiing keys and vals together:
(for [[brand models] cars
model (or (seq models) [nil])
:let [model-str (if model
(str " " model)
"")]]
(str brand model-str))
(also used let in an attempt to aid readability)what should the output look like?
is this right?
(let [car-names ["audi" "bmw" "fiat" "haval"]
car-models ["" ["x1" "i3"] "500" ""]]
(map vector car-names car-models))
;; => (["audi" ""] ["bmw" ["x1" "i3"]] ["fiat" "500"] ["haval" ""])
but i would adjust car-models
to be [[] ["x1" "i3"] ["500"] []]
, if possible
which gets you
(let [car-names ["audi" "bmw" "fiat" "haval"]
car-models [[] ["x1" "i3"] ["500"] []]] ;; empty list instead of empty string
(map vector car-names car-models))
;; => (["audi" []] ["bmw" ["x1" "i3"]] ["fiat" ["500"]] ["haval" []])
or even
(let [car-names ["audi" "bmw" "fiat" "haval"]
car-models [[] ["x1" "i3"] ["500"] []]] ;; empty list instead of empty string
(->> (map vector car-names car-models)
(into {})))
;; => {"audi" [], "bmw" ["x1" "i3"], "fiat" ["500"], "haval" []}
This is the desired output ; desired output of the function = “Audi, BMW X1, BMW i3, Fiat 500, Haval”
I’m going to try the empty lists
Is a threading macro basically equivalent to ocaml piping?
Yes I think so. Note that Clojure has thread-first -> and thread-thru ->>
https://clojuredocs.org/clojure.core/-%3E%3E and https://clojuredocs.org/clojure.core/-%3E
@rosenjcb the important difference is that OCaml piping is semantic, and clojure threading macros (as all macros) are syntactic - a pipe creates a series of applications, a threading macro does a code rewrite to be more concrete, OCaml piping can't do this:
user=> (->> (+ a b) (let [a 23 b 19]))
42
it also doesn't have this commonly seen newb trap error:
user=> (macroexpand '(-> y (fn [x] (+ x x))))
(fn* y ([x] (+ x x)))
lists of symbols that are not yet compiled is a lower level, more flexible, and more error prone domain compared to the operatioins the pipes do the macro rearranges symbols in lists, the pipe operator does higher order application and value capture
I think it's good style to use the clojure threading macros as if they were semantic, but you can't really use them fluently without understanding they are syntactic
hi! is this the appropriate channel for newbie cljs questions, or should that be in #clojurescript? 🙂
Here’s fine.
Thanks!
anyone knows if doing the tonsky-way formatting in atom is possible? (https://tonsky.me/blog/clojurefmt/ ) i tried tweaking the paredit plugin's regex but no luck...
Off topic: That site has an awesome dark mode!
hello! i have a question regarding structuring a part of an application I’m working on. It may not actually be a beginner question but Clojure is new to me so feel free to point me to another channel 🙂 I’m developing a REST API and have a need to run a worker process/thread long polling SQS for messages continuously and I wasn’t sure where to put something like that in my codebase nor how to kick off the process so it’s not blocking anything. Is there any code samples possibly or ideas on how to structure this and what part of the stdlib may help with this. FWIW I’m starting project this as a monolith. I have a lot of experience with building micro services but this is a solo project and micro services don’t feel appropriate at this stage of development.
Also if this question is too complex to answer in Slack I’m happy to post on clojureverse
@mike741 the answer that's usually good enough for your first draft is to use future
, which propagates bindings for dynamic vars, starts your code in a new thread (in an expandable thread pool) and returns a handle you can use to check exit or error status, or even cancel it if it calls cancellable methods like Thread/sleep periodically.
^ in general it depends on what you're wanting to do, but that suggestion is a good starting point
user=> (def f (future (loop [] (println "looping") (Thread/sleep 1000) (recur))))
#'user/f
user=> looping
looping
looping
looping
looping
looping
looping
looping
looping
looping
(future-cancel f)
true
the threading mixes up the program output and my input here, but it shouldn't be too hard to figure out
do note that future-cancel
is opt in - you need to call something that respects that it should abort if the current thread is cancelled (the jvm has code that isn't cancellation safe, so the method that actually no questions asked kills a thread isn't safe to use)
ok cool thank you for that pointer.. that seems pretty straightforward.. I’ll check that out.. Much appreciated!
for more advanced usages there are libraries like claypoole or the built in java executor service
personally i find manifold very easy to use
my use case is pretty simple.. poll SQS for messages, on receipt of message(s) loop through them and do a database update.
I just wasn’t sure which part of the stdlib I should start with to get a thread running out to the side continuously in order to support polling the queue. thanks again all!
How do I turn on the sql debugging with seancorfield/next-jdbc
?
@munichlinux What do you mean by “sql debugging”?
I am trying to log the sql statements.
There’s currently nothing built into the library for that. For execute!
and execute-one!
you could write a wrapper that logged the sql-params vector.
In theory you could write something like next.jdbc.default-options
that lets you wrap a connectable in something that would log the sql-params prior to calling the implementation.
There are some interesting edge cases: what should you do for a prepare
call? It doesn’t actually run the query, it just builds a PreparedStatement
, and in general you can’t get the actual SQL back out of those in a generic JDBC way. What about plan
which doesn’t do anything until it is reduced? What about sensitive data being passed in as parameters?
Logging result sets is even more fraught since they can be arbitrarily large — and for plan
they are not really exposed since the whole point is to reduce
over the ResultSet
, iterating across it without even producing Clojure data structures.