This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-12-07
Channels
- # adventofcode (114)
- # announcements (3)
- # aws (5)
- # babashka (62)
- # beginners (111)
- # calva (4)
- # cider (20)
- # clara (5)
- # clj-kondo (1)
- # cljs-dev (9)
- # clojure (255)
- # clojure-europe (75)
- # clojure-italy (10)
- # clojure-nl (3)
- # clojure-norway (5)
- # clojure-uk (6)
- # clojuredesign-podcast (5)
- # clojurescript (34)
- # community-development (28)
- # conjure (1)
- # cursive (3)
- # data-science (1)
- # datavis (1)
- # datomic (4)
- # figwheel-main (1)
- # fulcro (14)
- # graalvm (1)
- # graphql (8)
- # integrant (4)
- # introduce-yourself (2)
- # jobs (2)
- # juxt (4)
- # kaocha (2)
- # malli (6)
- # membrane-term (53)
- # mount (2)
- # nextjournal (2)
- # off-topic (27)
- # pathom (11)
- # polylith (3)
- # portal (11)
- # reagent (4)
- # reitit (4)
- # remote-jobs (1)
- # reveal (14)
- # shadow-cljs (22)
- # tools-deps (24)
- # vim (6)
- # xtdb (19)
loop/recur is great when you need more fiddly behavior around looping, which AoC includes a bunch of. I used loop/recur 3 times in the first 5 days
we have very similar solutions! I am happy to see you also wrote quite a lot of code for day 4. 🙂
it wasn't strictly necessary but it helped with clarity
Don't forget we have a dedicated #adventofcode channel!
I haven't done day 6 yet
reduce is another fiddly one, you can do a lot of different kinds of looping and even exit early with reduced
I suck at transducers
I really ought to read that section in Clojure, The Essential Reference
Interesting. The thing that got me thinking was finding (map vector a b)
was akin to Ruby's zip
. The way people use those few basic functions (definitely including reduce
) blows me away.
ahhh yeah, passing multiple collections to map does come in handy
it can also be used for rotating arrays of arrays https://gist.github.com/corasaurus-hex/ee69c4bdee71b55a1ebbcf588d82c527#file-4-1-clj-L24-L26
err I guess that should be transposing
I'd sit down with clojure.core/for, it can map, filter, take-while, mapcat, and do cross products
Hello everyone, I'm new to Clojure and I'm struggling with setting up the environment on Windows and VS code. Is there a good tutorial for that?
I found it much easier to use Vs code and wsl. Installing on Linux was much less painful and the vscode remote wsl support is top notch.
@U02PLQ02QUD I'll second what Stuart said: if you can use WSL2 for your development, I would strongly recommend it. It's how I work. VS Code on Windows with the remote-wsl2 extension installed; everything Clojure-related on Linux (Ubuntu) on WSL2; VS Code makes it feel like everything is local on Windows -- and you avoid any and all weirdness around pathing/quoting and you'll find nearly all the tutorials and books assume macOS/Linux so it'll make your life a lot easier in that respect.
@U013YN3T4DA @U04V70XH6 Thank you so much
Is it possible to create a future
with the thread local of the parent thread that created the future?
generally speaking no, that isn't how thread locals work, futures run on another thread
Ah got it, thanks. I was hoping there’d be a nice workaround somewhere. Could just set the values again in the future body.
however dynamic bindings from the creating thread also exist when a future executes
the caveat there is they are only set!'able on the thread that did the dynamic binding
and that propagation is something clojure does specially for future and agent actions, if you create a thread by some other means the bindings won't get propagated, you can using something like bound-fn in that situation
got it thank you
that’s interesting actually, i wasn’t aware of what a future would capture
our company java library relies on thread local values for logging. so when we spawn futures from a thread the logger doesn’t function.
If you haven't found the answer yet, https://clojure.org/reference/java_interop#_calling_clojure_from_java should have most of the details you need. The caveat would be if list1
and list2
live in a Clojure namespace, in which case you'd need to cast the results of Clojure.var
for them to a clojure.lang.Var
so that you can call deref
on them before passing them to map
. Why? Because without the deref
, you'd be doing the equivalent of (map #'map-fn #'list1 #'list2)
.
Is there a way to catch an AssertionError produced by pre-post-conditions? E.g. the try block below doesn't catch the error:
(defn string-to-string [str]
{:pre [(string? str)]
:post [(string? %)]}
str)
(comment
(string-to-string "str")
(string-to-string 10)
(try
(string-to-string 10)
(catch Exception e
(prn "caught" e)))
*e)
hi, new to clojure.spec, using it for data-validation,
what would be an idiomatic way to transform spec action to client-error message?
my logic is mostly:
if (spec/valid? spec req-body): XYZ, else: return 422 "invalid req-body"
but i'd like to improve the error msg to be more specific,
1. I have looked onto expound
but prefer not to add another dependency,
2. I can generate logic on (s/explain-data)
data structure result,
so (2) seems like a good direction -- is this common? thx!
I have a collection (vector) that I would like to lazily transform into a map. How do? for
produces a seq - no good; reduce
isn't lazy; make my own with lazy-seq
? I feel like I'm glossing over something here.
https://github.com/Malabarba/lazy-map-clojure never say never 😛
this is only lazy in the values -- it delays their computation, but the keyset is fixed
Hmm, so if I want to delay evaluation, produce a seq of entries instead of a map and then into {}
when I go to realize it?
I think wrapping the map-generation in a lazy-seq
would also have the desired effect of delaying map computation, no?
do you want to lazily populate a map with values when they are looked up? It sounds like you might want a cache
but it seems like there are some things that are at cross purposes. Having a sequence involved means you have to realize a bunch of entries in order to find the entry you want. Which doesn’t seem great. If you can manage to go from a seq based computation to more direct computation, perhaps a cache or a memoized function would provide what you are wanting?
No, I have a data source that lazily gives me some starting values. I want to augment those values with some of my own computations but delay the computations until my consumer is ready for the chunk.
Asked coz there could be key collisions if they key was also going to be computed lazily. I think the library you linked is quite interesting.
Has anyone ever done tutoring for clojure? Is that a thing? Has anyone tried being tutored and found it to be helpful? Do you know where I'd find one? I tried looking at online tutor websites but clojure is too niche for those I think
Cool I will think about it thanks
I've never used discord before so I'll have to try it out
Do I just go to http://discord.com and search for emccue#1975?
🙌:skin-tone-4:
Can anybody tell me how to change this to only run (filter …) (if video-title-filter)?
(->> playlist-items
(filter (fn [playlist-item] (str/includes? (str/lower-case (get-in playlist-item [:snippet :title] "")) video-title-filter)))
(transform-playlist-items))
Looks like I might have to use (cond->>)
but can’t quite figure out how it would fit this example
I think this does the trick:
(cond->> playlist-items
(some? video-title-filter) (filter (fn [playlist-item] (str/includes? (str/lower-case (get-in playlist-item [:snippet :title] "")) video-title-filter)))
true (transform-playlist-items))
I see some people prefer some?
for things that aren't booleans to better communicate that this thing is either nil or not-nil (and false
doesn't make sense for the thing).
Any thoughts on that?
ah, got that from here: https://stackoverflow.com/questions/11854392/clojure-not-nil-check
if you want that unconditionally applied and are using cond->>, then yeah you need the true
(filter (fn [playlist-item] (str/includes? (str/lower-case (get-in playlist-item [:snippet :title] "")) video-title-filter)))
i’m going to leave the filter fn for now in order to make a release and get some sleep ha
I'm not directly answering your question, but I like not to mix "complex" stuff with simple ones, espacially when using the -> macro. Something like:
(defn filter-playlist-items [title-filter playlist-items]
...)
(->> playlist-items
(filter-playlist-items video-title-filter)
(transform-playlist-items))
is more readable, for me, and it's easier to add if
in the function without converting the whole ->>
into a cond->>
. Also you can unit test the filter-playlist-items
function independently.Thanks! You make a good point about the testability of the new filter-playlist-items fn
I usually try to make filter work without abstracting filter away from the place it's used
I find the easiest way to test these kinds of things is to ensure that you have a single pure predicate and then wire it up with (filter pred ...)
. Testing filter-playlist-items
tends to be a bit more annoying that testing a predicate returned from (title-filter args)
True! But here he wanted to add some extra code around the filter (make it conditionnal to some variable). It is still possible to create another function just for the inner filter predicate.
my suggestion in the next comment is to put the conditional inside of the filter function and then unconditionally always use that filter pred
I read it afterwards yes, it's elegant even if a bit suboptimal
Also, another way to get around the cond->
is if your title-filter is the function that does the no-op. Ie, always create and filter using the title filter, but if there is no snippet title to filter on, have it return true on all movies (transform (filter (title-filter args) items))