This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-12-13
Channels
- # adventofcode (36)
- # aleph (1)
- # announcements (7)
- # aws (4)
- # babashka (14)
- # beginners (61)
- # calva (79)
- # cider (19)
- # clojure (48)
- # clojure-austin (1)
- # clojure-australia (2)
- # clojure-czech (2)
- # clojure-europe (46)
- # clojure-france (8)
- # clojure-nl (19)
- # clojure-uk (4)
- # clojuredesign-podcast (14)
- # core-logic (42)
- # data-science (3)
- # datalevin (8)
- # datomic (76)
- # events (1)
- # figwheel-main (9)
- # fulcro (6)
- # helix (1)
- # holy-lambda (1)
- # honeysql (2)
- # jobs (2)
- # jobs-discuss (20)
- # leiningen (5)
- # lsp (87)
- # minecraft (11)
- # nextjournal (4)
- # off-topic (17)
- # practicalli (1)
- # reagent (22)
- # reitit (8)
- # releases (3)
- # rum (2)
- # shadow-cljs (18)
- # sql (11)
- # tools-build (5)
- # tools-deps (9)
- # xtdb (20)
Is it possible, to have some side-effecty thing as a binding in a doseq and still doing side effects in the body? Like this:
(doseq [x (range 0 3)
_ (log/info "LOG" x)
y ["a" "b" "c"]]
(spit "test_doseq.txt" [x y] :append true))
the problem is that you aren't consuming _
doseq is a big weird macro, it has a lot of counterintuitive corner cases, inevitably
Great, it works! Yes, it is perhaps better to just have the other doseq inside the body for readability. Thank you for your time.
It seems to only do the first side-effect here. I want to log something only when x is different than the previous one without embedding another doseq in the body just so I can have a log.
(defn add-submap [m new-key new-keys-value]
(reduce-kv
(fn [acc k v]
(assoc acc k (assoc v new-key new-keys-value)))
{}
m))
=> (add-submap {:a {:b 1} :c {:d 2} :e {:f 3}} :email-verified nil)
=> {:a {:b 1, :email-verified nil}, :c {:d 2, :email-verified nil}, :e {:f 3, :email-verified nil}}
took me a little while to wrap my head around what was going on, but it was satisfying to figure out! š
Does anyone know of a good resource (books, talks on YouTube, blog posts, etc.) which provide a high-level overview of best practices and libraries for āfull-stack web developmentā using Clojure (back-end) and ClojureScript (front-end)? Iām looking for a resource to give me the ālay of the land,ā so to speak. A bit more context: Coming from a background of using ālanguage/framework pairsā such as PHP/Laravel, Python/Django, Ruby/Rails and Elixir/PhoenixāIām struggling with the fact that, with Clojure, the recommended approach is to compose various libraries, such as Ring, Compojure, Reitit, Pedestal, Re-agent, Re-frame, Hiccup, Garden, etc. I see there are also some āhigher-level libraries,ā such as Luminus and Fulcro. Iām searching for something that will teach me how to choose and compose the ārightā libraries, in lieu of a framework. Note that I have already purchased a copy of āhttps://pragprog.com/titles/dswdcloj3/web-development-with-clojure-third-edition/,ā which Iām hoping will be a good starting points. From skimming through the table of contents and reviews, it seems to be focused on Luminus. (?) Iām looking forward to working through that book during my upcoming Christmas vacation.
I think this is a good introduction to fullstack clojure webdev https://pragprog.com/titles/dswdcloj3/web-development-with-clojure-third-edition/
Thanks, @UBRV1HXPD! I purchased that book a few weeks ago, and Iām planning to read it over the Christmas holidays.
I'm gonna say Compojure with Ring on the backend Rum via Shadowcljs on the frontend mix and match static and js however you need Selmer for templating html
Pedestal on the backend is also good for routing / middleware (instead of Ring)
Thanks for the tips, @U3ES97LAC!
I am trying to more aware of how i setup my functions, and I maybe got to a state where i overthink it waay to much. This is a very basic example, but even here I have doubts: I have a validation function that validates an object in an s3 bucket. This function needs to verify that a virus-scan-status is clean as well as a bunch of other stuff. Let me use the virus scanning as example.
(defn is-virus-scan-clean? [s3-client s3-bucket-name s3-key]
"Returns true if the virus scan is clean"
(let [scan-status (get-virus-scan-status! s3-client s3-bucket-name s3-key)]
(= "CLEAN" scan-status)))
(defn is-virus-scan-clean2? [scan-status]
(= "CLEAN" scan-status))
;; I HAVE LEFT OUT SOME OTHER VALIDATION DETAILS IN THESE FUNCTIONS TO MAKE IT CLEARER
(defn validate-s3-object [s3-client s3-bucket-name s3-key]
{:virus-clean? (is-virus-scan-clean2? (is-virus-scan-clean? s3-client s3-bucket-name s3-key))})
(defn validate-s3-object2 [s3-client s3-bucket-name s3-key]
(let [scan-status (get-virus-scan-status! s3-client s3-bucket-name s3-key)]
{:virus-clean? (is-virus-scan-clean2? scan-status)}))
Here i have 2 functions. Function1 first fetches the relevant scan-status inside the is-virus-scan-clean? function. This i currently find the best, however, it is not very pure. I also find it weird that i parse in a bunch of s3-info stuff to this function. Function2 receives the scan-status as input and therefore the function itself is pure. However it doesn't seem like there is much i gain from this function being pure. However i like that this function does not need any s3-info stuff to perform this action. Maybe there is no correct answer, but i would like to hear what people think about thisI prefer the second approach, since (as you've mentioned) it leads to more pure functions. Also, the first approach violates the single responsibility principle: it fetches the status and checks it.
The benefit of the second, "more pure functions" approach isn't as clear in a tiny example like this, but pure functions are generally easier to reason about and test.
Maximizing for function purity also has the positive side effect of pushing side effects closer to the boundaries of your program, isolating it to some known subset of your code base.
(I forget which book/article I learned that from, but it was a pretty profound realization. In the book/article the author was building up an RDD solution to a problem, continuously refactoring the working code to factor out pure functions. It was beautiful to see it applied and what the results are. )
That makes sense. Sounds very interesting. If you find out the name of the book/article please let me know!
I think it might have been this talk: https://invidious.snopyta.org/watch?v=vK1DazRK_a0 by Rafal Dittwald
The https://libredd.it/r/programming/comments/bt84iq/solving_problems_the_clojure_way_video/ of that video also has some relevant discussion. The more common phrase "pushing side-effects to the system edges" is used there, as well as "functional core, imperative shell", which is often referenced.
So bascially its a question if its better to group all the sideeffects to wind up in the outer validation function to then go on calling a bunch of pure functions. Or if its better to call the function with sideeffects in the function that needs the result of said sideffect
Is there a clojure spec (1) way to easily specify N (hardcoded) repeats of something? Or just s/cat
and hardcode :entry1,
:entry2
, :entry3
ā¦?
As a simple example: how would you spec a tic-tac-toe game field, as a vec of vecs (3x3)?
spec/coll-of
has :count
and :kind
parameters, which I think would get you what you're looking for.
Another spec question: is there an spec for an interposed string? E.g. conforming āhello,hello,hello,helloā with as relevant elements the string āhelloā
and character \,
regular expression will be my 2 bits of suggestion...
Fair enough. I was hoping to be able to compose specs here, as instead of āhelloā
I might have stricter requirements on my repeating element.
Nothing built in for that
It technically still uses regex, but you could use the string library's split method with separator #"hello" and then validate the remaining strings via spec/coll-of.
What is the difference between on-change
and value
here ?
(defn page [ratom]
[:div
[:p
"Please enter your name: "
[:input {;:on-change #(swap! ratom %)
:on-change (fn [evt]
(reset! ratom (-> evt .-target .-value)))
:value @ratom}]]
[:p "Your name is " @ratom]])
value is what the contents of the input field will be when that part of the page is rendered. on-change describes an event that is fired when you edit the contents of the input field (sort of) This has nothing to do with clojure or clojurescript btw. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-value https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onchange
I am, but my code has a problem I can't find that means I'm not terminating the recursion properly so it goes on forever, was hoping to set it to a low number so instead of going on forever it just stops after n recurs
what's your editor? nevermind, I misread the question
I know there is INteruppt running evaluation, but for reasons I dont understand sometimes it doesnt stop and I have to kill the repl altogether
e.g.
(loop [my-counter 0
[h & t] some-list]
(if (= my-counter 10)
"DONE"
(recur (int my-counter) t)))
funny enough, int
is obviously a typo but would not error :D
Are you trying to increase that limit or lower it? From some quick reading, it looks like the jvm doesnāt expose this directly, but you can influence it by setting the stack size for the jvm
I'm using recur, but I'm debugging an issue in my code where i'm not terminating the recursion as I think I am. So it goes on forever, and sometimes I'm having to kill the repl. I was just wondering if I could maybe set it to 20-30 or something
ah. i was assuming actual calling the function style recursion rather than looping. In this case you are in complete control of the control flow. Add an extra parameter (often called āgasā) and throw an error when it is above some threshold
ah ok, i guess i could do something like
(loop [stuff, more stuff, x]
(if (= x 10)
:stop
(recur ojdfp djsdo (inc x))
Thanksanother good trick is (when (zero? (mod x 100)) (println ....))