This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-12-25
Channels
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))
(->> points
(mapcat neighbours)
(remove points)
count)
What would be considered most idiomatic? 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
(count
(for [point points
neighbour (neighbours point)
:when (not (contains? point neighbour))]
neighbour))
which is simply not possible in the second onefor fun, here’s what our new overlords have to say about the matter
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.
They appear to be doing the same thing
Because neighbour depends on point, it can't be a product
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.
What makes it inappropriate?
Why should it only be used for that?
You can also do permutations with nested maps
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