This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-04-12
Channels
- # announcements (1)
- # babashka (67)
- # beginners (39)
- # calva (56)
- # clojure (72)
- # clojure-berlin (3)
- # clojure-boston (1)
- # clojure-europe (10)
- # clojure-nl (1)
- # clojure-norway (67)
- # clojure-uk (5)
- # clojurescript (7)
- # emacs (21)
- # figwheel-main (5)
- # graalvm (24)
- # hyperfiddle (26)
- # missionary (5)
- # music (1)
- # off-topic (21)
- # polylith (4)
- # releases (2)
- # sci (3)
- # shadow-cljs (25)
- # squint (28)
Why is there an anonymous fn within the lazy-seq instead of a simple loop binding? This is from the implementation of clojure.core/distinct btw.
([coll]
(let [step (fn step [xs seen]
(lazy-seq
((fn [[f :as xs] seen]
(when-let [s (seq xs)]
(if (contains? seen f)
(recur (rest s) seen)
(cons f (step (rest s) (conj seen f))))))
xs seen)))]
(step coll #{}))
Presumably, it's to act as the recur
target if the value has already been seen.
I mean, why not a loop?
Oh right
This is a neat hack. I’m going to steal it
I always wrote a loop in a condition instead of doing it this way. So elegant
To be honest, I'm not sure why it doesn't use a loop instead. A looping version might look like:
(let [step (fn step [xs seen]
(lazy-seq
(loop [xs (seq xs)
seen seen]
(if xs
(let [x (first xs)]
(if (contains? seen x)
(recur (next xs) seen)
(cons x
(step (next xs) (conj seen x)))))))))]
(step coll #{}))
This seems to behave similarly, but there might be some subtle differences in how lazy the result is. Since this was added in 1.0, it's also possible that it could theoretically be improved, but is not worth changing for theoretical benefits given the risk of breaking existing code in a subtle way.
I don't don't know for sure.Yes. I wrote it similarly too, which was why my question in the first place
I guess because the anonymous function has been named step
and that name has been used in the call itself?
Talking about the name given besides fn
and not in the let binding.
Are there any other sequence processing functions besides reduce
that can be short circuited with reduced
value or similar?
thanks, iteration is interesting and I always forget about it
Ah, and, of course, anything that uses reduce
itself and passes it a function that can return reduced
. I see reduce-kv
and run!
, maybe there are others.
Ended up just manually writing loop recursive
why does splitv-at
in clojure 1.12 return a vector for take
and a seq for drop
? why not both vectors?
I don't know the actual reasoning, but doing it this way prevents fully realizing seqs.
(defn split-at
"Returns a vector of [(take n coll) (drop n coll)]"
{:added "1.0"
:static true}
[n coll]
[(take n coll) (drop n coll)])
this is the new 1.12 splitv-at
yeah that makes sense
(split-at 10 (range))
works, so should (splitv-at 10 (range))
Well, "X works so should Y" is by itself not a very good basis. :)
map
works on inf seqs, mapv
doesn't. Well, it does work but it hangs, of course.
That doesn't really answer the question in the OP of "why not (into [] (drop n) coll)
".
yeah it answers the "why does this exist" and i understand that the goal is efficiently splitting at a specific point, which the IDrop interface provides.
i guess it's just "implementation details" for why they're different types
it is designed for the case where you are splitting your way through an arbitrary collection (which may be lazy / infinite)
retaining the collection type for the remainder allows you to continue efficiently dropping from it without incurring the cost to copy the data into another collection
that makes sense, thank you for the explanation
partitionv[-all] is one way to do this, but splitv-at is better for the explicit loop/recur variant of that where you have more control over when to stop
both split-at
and splitv-at
get the drop advantages, it's just whether you want your partitions as vectors or seqs (vectors matches partitionv
- that change is why we introduced a new function there, to avoid breaking existing assumptions)
that makes sense. the lack of a vector in the drop branch feels incongruent with the other -v functions but it's a small price to pay
it is a vector in the place where that's important
Is this the intended behavior for when-let
? It does something surprising with associative deconstructing:
(defn test-when-let [k]
(let [m {:foo "foo"}]
[(when (m k)
{:first (m k)})
(when-let [bar (m k)]
{:second bar})
(when-let [{bar k} m]
{:third bar})]))
;; returns [{:first "foo"} {:second "foo"} {:third "foo"}]
;; all good!
(test-when-let :foo)
;; returns [nil nil {:third nil}]
;; was expecting [nil nil nil]
(test-when-let :bar)
ah that makes sense, counter intuitive at first but more obvious if you deconstruct with more than one binding
clojure.core/when-let
([bindings & body])
Macro
bindings => binding-form test
When test is true, evaluates body with binding-form bound to the value of test
java.lang.ClassNotFoundException: sun.misc.Launcher$ExtClassLoader
Anyone knows the cause/fix, when trying to upgrade from Java8 to Java17 using Clojure 1.10.0
[java] Exception in thread "main" java.lang.ExceptionInInitializerError [java] at dynapath.defaults__init.load(Unknown Source) [java] at dynapath.defaults__init.<clinit>(Unknown Source) [java] at java.base/java.lang.Class.forName0(Native Method) [java] at java.base/java.lang.Class.forName(Class.java:467) [java] at clojure.lang.RT.classForName(RT.java:2207) [java] at clojure.lang.RT.classForName(RT.java:2216) [java] at clojure.lang.RT.loadClassForName(RT.java:2235) [java] at clojure.lang.RT.load(RT.java:453) [java] at clojure.lang.RT.load(RT.java:428) [java] at clojure.core$load$fn__6824.invoke(core.clj:6126) [java] at clojure.core$load.invokeStatic(core.clj:6125) [java] at clojure.core$load.doInvoke(core.clj:6109) [java] at clojure.lang.RestFn.invoke(RestFn.java:408) [java] at clojure.core$load_one.invokeStatic(core.clj:5908) [java] at clojure.core$load_one.invoke(core.clj:5903) [java] at clojure.core$load_lib$fn__6765.invoke(core.clj:5948) [java] at clojure.core$load_lib.invokeStatic(core.clj:5947) [java] at clojure.core$load_lib.doInvoke(core.clj:5928) [java] at clojure.lang.RestFn.applyTo(RestFn.java:142) [java] at clojure.core$apply.invokeStatic(core.clj:667) [java] at clojure.core$load_libs.invokeStatic(core.clj:5985) [java] at clojure.core$load_libs.doInvoke(core.clj:5969) [java] at clojure.lang.RestFn.applyTo(RestFn.java:137) [java] at clojure.core$apply.invokeStatic(core.clj:667) [java] at clojure.core$require.invokeStatic(core.clj:6007) [java] at clojure.core$require.doInvoke(core.clj:6007) [java] at clojure.lang.RestFn.invoke(RestFn.java:421) [java] at dynapath.util$loading__4920__auto__.invoke(util.clj:1) [java] at dynapath.util__init.load(Unknown Source) [java] at dynapath.util__init.<clinit>(Unknown Source) [java] at java.base/java.lang.Class.forName0(Native Method) [java] at java.base/java.lang.Class.forName(Class.java:467) [java] at clojure.lang.RT.classForName(RT.java:2207) [java] at clojure.lang.RT.classForName(RT.java:2216) [java] at clojure.lang.RT.loadClassForName(RT.java:2235) [java] at clojure.lang.RT.load(RT.java:453) [java] at clojure.lang.RT.load(RT.java:428) [java] at clojure.core$load$fn__6824.invoke(core.clj:6126) [java] at clojure.core$load.invokeStatic(core.clj:6125) [java] at clojure.core$load.doInvoke(core.clj:6109) [java] at clojure.lang.RestFn.invoke(RestFn.java:408) [java] at clojure.core$load_one.invokeStatic(core.clj:5908) [java] at clojure.core$load_one.invoke(core.clj:5903) [java] at clojure.core$load_lib$fn__6765.invoke(core.clj:5948) [java] at clojure.core$load_lib.invokeStatic(core.clj:5947) [java] at clojure.core$load_lib.doInvoke(core.clj:5928) [java] at clojure.lang.RestFn.applyTo(RestFn.java:142) [java] at clojure.core$apply.invokeStatic(core.clj:667) [java] at clojure.core$load_libs.invokeStatic(core.clj:5985) [java] at clojure.core$load_libs.doInvoke(core.clj:5969) [java] at clojure.lang.RestFn.applyTo(RestFn.java:137) [java] at clojure.core$apply.invokeStatic(core.clj:667) [java] at clojure.core$require.invokeStatic(core.clj:6007) [java] at clojure.core$require.doInvoke(core.clj:6007) [java] at clojure.lang.RestFn.invoke(RestFn.java:436) [java] at bultitude.core$loading__5569__auto____3.invoke(core.clj:1) [java] at bultitude.core__init.load(Unknown Source) [java] at bultitude.core__init.<clinit>(Unknown Source) [java] at java.base/java.lang.Class.forName0(Native Method) [java] at java.base/java.lang.Class.forName(Class.java:467) [java] at clojure.lang.RT.classForName(RT.java:2207) [java] at clojure.lang.RT.classForName(RT.java:2216) [java] at clojure.lang.RT.loadClassForName(RT.java:2235) [java] at clojure.lang.RT.load(RT.java:453) [java] at clojure.lang.RT.load(RT.java:428) [java] at clojure.core$load$fn__6824.invoke(core.clj:6126) [java] at clojure.core$load.invokeStatic(core.clj:6125) [java] at clojure.core$load.doInvoke(core.clj:6109) [java] at clojure.lang.RestFn.invoke(RestFn.java:408) [java] at clojure.core$load_one.invokeStatic(core.clj:5908) [java] at clojure.core$load_one.invoke(core.clj:5903) [java] at clojure.core$load_lib$fn__6765.invoke(core.clj:5948) [java] at clojure.core$load_lib.invokeStatic(core.clj:5947) [java] at clojure.core$load_lib.doInvoke(core.clj:5928) [java] at clojure.lang.RestFn.applyTo(RestFn.java:142) [java] at clojure.core$apply.invokeStatic(core.clj:667) [java] at clojure.core$load_libs.invokeStatic(core.clj:5985) [java] at clojure.core$load_libs.doInvoke(core.clj:5969) [java] at clojure.lang.RestFn.applyTo(RestFn.java:137) [java] at clojure.core$apply.invokeStatic(core.clj:667) [java] at clojure.core$require.invokeStatic(core.clj:6007) [java] at clojure.core$require.doInvoke(core.clj:6007) [java] at clojure.lang.RestFn.invoke(RestFn.java:3659) [java] at cloverage.coverage$loading__5569__auto____1.invoke(coverage.clj:1) [java] at cloverage.coverage__init.load(Unknown Source) [java] at cloverage.coverage__init.<clinit>(Unknown Source) [java] at java.base/java.lang.Class.forName0(Native Method) [java] at java.base/java.lang.Class.forName(Class.java:467) [java] at clojure.lang.RT.classForName(RT.java:2207) [java] at clojure.lang.RT.classForName(RT.java:2216) [java] at clojure.lang.RT.loadClassForName(RT.java:2235) [java] at clojure.lang.RT.load(RT.java:453) [java] at clojure.lang.RT.load(RT.java:428) [java] at clojure.core$load$fn__6824.invoke(core.clj:6126) [java] at clojure.core$load.invokeStatic(core.clj:6125) [java] at clojure.core$load.doInvoke(core.clj:6109) [java] at clojure.lang.RestFn.invoke(RestFn.java:408) [java] at clojure.lang.Var.invoke(Var.java:384) [java] at clojure.lang.Util.loadWithClass(Util.java:250) [java] at cloverage.coverage.<clinit>(Unknown Source) [java] Caused by: java.lang.ClassNotFoundException: sun.misc.Launcher$ExtClassLoader [java] at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) [java] at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) [java] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) [java] at java.base/java.lang.Class.forName0(Native Method) [java] at java.base/java.lang.Class.forName(Class.java:375) [java] at dynapath.defaults$fn__68.<clinit>(defaults.clj:12) [java] ... 100 more
Hum, I don't think it's in the dependency chain. I am runing cloverage though, and error is coming from that
The root cause is at [java] at dynapath.defaults$fn__68.<clinit>(defaults.clj:12)
and before, which is not shown.
dynapath.defaults
used to be a vendored namespace in CIDER nREPL in 0.18.
Nah, probably not that. That line seems to only extend classloader types to some protocols.
Oh, no - that is that. I was looking at a newer version. Here it is: https://github.com/tobias/dynapath/blob/0.2.5/src/dynapath/defaults.clj#L40
Anyone know of a library for diffing sequences a la the diff
POSIX command? I.e., no deep diff, and able to detect insertions and deletions rather than just comparing index-by-index.
I could literally just shell out to diff
if I really have to, but...
Yeah, when I needed to diff two JSON files printed out for humans, I ended up with shelling out to diff
. :) Couldn't find a more reasonable solution.
Hmm if that's a gap in the ecosystem... adds to list of yaks to be shaven later
It might've easily be a gap in my ability to search.
Or a gap in the ecosystem w.r.t. my own very particular needs at the time. It could easily be that your needs are different enough, or that enough time has passed since then, that now there's a thing you can use instead of bin/diff
.
I should add that my needs included the best performance available since it was about relatively large JSON objects.
For smaller data, maybe even diff2
by LambdaIsland can be enough, despite it being a deep diff.
I could make a deep diff work by doing something like stringifying the data, as long as it can detect insertions. Really I just need the right hand side of the diff. I am looking for items on the right side which are unaccounted for on the left side, where the items are not necessarily unique but are sorted.
And I'm looking for them by position in the original right hand side list, because I'll be stripping some data away for the comparison which I must then reconstitute. Configurable equality semantics could achieve that too I suppose
There's also this, maybe helpful, dunno: https://github.com/juji-io/editscript
Oh hmmm. I'd passed over that, but yeah that might do it. I'll do some tinkering. Thanks!