This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
I was solving an AOC puzzle, and wrote a part in two ways:
(count (for [point points neighbour (neighbours point) :when (not (contains? points neighbour))] neighbour))
What would be considered most idiomatic?
(->> points (mapcat neighbours) (remove points) count)
I think it’s a matter of personal preference.
Personally, I’d say the second one is more idiomatic and I prefer it.
I usually use
for loops when there is nested iteration (e.g.
(for [x … y …] [x y]))
imo, the threads also make it clearer what is happening from a data flow perspective and don’t introduce a lot of name bindings (“variables”) which means less noise when trying to understand what’s going on
You can read the threading guide if you haven't done so yet, it has some important points, such as to when use thread first or thread last (https://clojure.org/guides/threading_macros)
for example, the first one could have a typo like this
which is simply not possible in the second one
(count (for [point points neighbour (neighbours point) :when (not (contains? point neighbour))] neighbour))
these 2 solutions are doing very different things (macro expand the for). for is doing a nested iteration on 2 collections. for each point iterate over neighbours. then the condition in the iteration is sorta also an iteration over points. this is really confusing.
the macro expansion of the for solution will show you that it's doing a lot more than the threaded solution
i looked over the
for again, and i just noticed that the second collection is derived from the first. i haven't actually seen something like this before. i wasn't aware for could do that.
i still think that in this case
for is being used inappropriately. it's better to use it for permutations.
maybe there are other good use cases for
for could you show me some examples? i've only seen it be good for permutation stuff
yeah, that's what
for expands into, nested loops, which look like nested maps when you aren't doing filtering
My point is - you can do the same thing in either, it's just a matter of preference and readability
if you have good examples of
for for other use cases, i'm interested. i imagine it's ok with graph stuff, but then there are graph libs that probably just are better to use.
in this specific use case, the for solution uses 3 nested loops. the threaded solution uses 2
these are not doing the same thing, and also one is more readable than the other. for is not the right tool for this job, and it's less readable as well.
Perhaps off-topic, but is there any way I can peek into the java process that is running my CIDER repl to see if it has open file handles, and things of that sort?
are you looking for a java-specific method? On Linux (and I think macOS) you should be able to do
lsof -c java or
lsof -p <PID of CIDER process> to list open handles and sockets. On Windows you could use https://learn.microsoft.com/en-us/sysinternals/downloads/handle or https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer to do the same from CLI or GUI