This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-05
Channels
- # aleph (6)
- # announcements (2)
- # babashka (8)
- # beginners (121)
- # calva (7)
- # cider (7)
- # clj-kondo (25)
- # clojure (167)
- # clojure-android (1)
- # clojure-italy (1)
- # clojure-sweden (1)
- # clojuredesign-podcast (2)
- # clojurescript (11)
- # community-development (33)
- # cursive (23)
- # data-science (1)
- # datascript (11)
- # datomic (7)
- # emacs (12)
- # events (1)
- # fulcro (15)
- # graalvm (3)
- # hoplon (1)
- # instaparse (1)
- # malli (12)
- # off-topic (1)
- # planck (3)
- # re-frame (5)
- # shadow-cljs (61)
- # test-check (2)
PSA: We just released some changes to Clojars. - rsyncing of the Clojars repo is now disabled (see https://github.com/clojars/clojars-web/issues/735) - GET or HEAD requests to the on-disk repo will now redirect to the CDN-fronted repo (see https://github.com/clojars/clojars-web/issues/734). This means that GET https://clojars.org/repo/whatever will return a 302 Found status code with a location header pointing to https://repo.clojars.org/whatever. We'll change that to a 301 Moved Permanently once this change has had time to settle and we don't have any issues reported that causes us to revert the change. Resolving dependencies should continue to work, since aether (the lib used by boot/lein/maven/tools.deps to resolve dependencies) should follow redirects correctly. Deploying to Clojars should be unaffected by this change - you can still deploy to https://clojars.org/repo/ or https://repo.clojars.org. If you (or someone you love) is negatively affected by either of these changes, please let us know by commenting on one of the above issues. See https://groups.google.com/d/msg/clojure/ZXBOQD5Ubbc/D4ktv8aFCQAJ for the rationale.
But nothing prevents repeatedly redefining the same var right? Namespaces are inherently mutable objects
`(do [email protected](map #(list 'def (vary-meta % assoc :declared true)) names))
I kind of would think it best if (def a)
was a compile error. Since it feels like a mistake to me, or at least a pretty bogus thing.
I’ll go grep the source in a minute, but I’m guessing there’s special casing for unbound vars in the compiler
I guess I'm a bit surprised by it. I'd have thought that (def a)
would be a compile error. Even more so that (def a) (a)
would be one. But it isn't.
it looks like the only place that checks for the :declared
meta is now no longer used? includesExplicitMetadata
seems never called
I think it's used to check whether you're re-def'ing something and whether the signatures, if any, are different.
Interesting, the meta makes it feel like maybe it wanted to not allow an unbound def unless it was specifically a declared one. But who knows
You do not get exception attempting to eval the second expression of (def a) (a)
?
i think the thought was that (declare a)
didn't do any more work than just (def a)
. was expecting a compiler error rather than a runtime error
I assumed since there is declare, that the reason was because an empty def was not allowed.
(declare a)
followed by a call to a
that is inside of another defn
is not a compiler error by design, yes?
That's the primary use case for declare
Ya, I understand for declare. What surprised me is that is is also true of (def a) (a)
Sorry, I may be catching up to what you meant earlier.
this is not true in clojurescript though. There the analyzer does use the metadata set from being declared rather than def'ed without an object
I've seen declare
used in a few projects, but don't recall ever seeing anyone do def
without a value.
Sorry, wrong example above, I mean: (def a) (defn some-other-fn [] (a))
or some like that
Eh, it's at most a weird wrinkle that affects pretty much no one.
Where I'd have expected (def a) to throw a compile error, and that you'd need to use declare instead.
There are much subtler bugs in code I've seen.
ClojureDocs has a note about declare that says you can also use (def a) instead. I feel we should almost delete that note :thinking_face:
that don't cause exceptions or obvious failures.
Like, see if you notice the bug here:
(deftest my-critical-test
(= 5 (some-important-function {:a 1 :c 4})))
The man wins a prize! Not very obvious in a big file of tests, though, and I've seen dozens of projects with them. Granted, maybe not for "critical' tests, but they lie there doing nothing useful, catching no problems.
Ya, I agree. I'm surprised deftest doesn't validate that. Would there ever be a reason to deftest without an is inside?
Some tests care only that no exception was thrown, they don’t need is
for that.
Although, I suppose if you want to see the little green marker in Cursive or CIDER, you can throw an (is true)
after the thing that might have blown up… 🙂
also, you can invoke is
inside a function inside a test, since is
is dynamic, not lexical
missing is. No compiler warning or error. No run-time error.
Sorry, that was Slack doing something weird with a colon followed by a b
I've edited it, which is unfair to your former answers. The missing is is the only mistake I intended to write.
One of the first things I implemented in Eastwood
Ah that's good actually. Got eastwood running at work, glad it's got that check and I don't need to worry about our tests having that problem 😛
Along with finding this mistake:
(deftest my-good-tests
(is (= 5 (something-important {:a 1 :c 5}))))
(deftest my-good-tests
(is (= 7 (something-else-important 8))))
If you want a hint: very easy copy-and-paste mistake to make while maintaining a test file
yes. The first ones never get run. No compiler error or warning. No run-time issues.
And an existing Eastwood one for a few years.
It's certainly nice if clj-kondo can do everything Eastwood does and more, given how much attention borkdude puts into it.
I like Eastwood, but its pretty slow to run, which is why I have it only setup to run on build, and not like inside my editor as I type
I feel clj-kondo is the best thing to happen to Clojure in the last year 😛 Sorry to any other amazing thing I'm forgetting. But for me, it has been a huge help to quickly correct some stupid mistakes like that. And its also great for beginners to help them out.
There's a lot of things I feel I always wanted the Clojure compiler to catch and make as errors, which clj-kondo addresses as a linter.
Toss borkdude a hat tip of thanks when you see him next -- I don't know how much time he spends on that and other projects, but it seems huge.
He's been on fire. clj-kondo, sci and babashka are probably the 3 Clojure projects I'm most excited about to see grow in the next few years.
@didibus @andy.fingerhut there's also https://github.com/borkdude/missing.test.assertions for catching missing test assertions at runtime which is a pretty simple and small but effective lib

Re #eastwood slowness. Most of it is caused by the analyzer. I’ve got a patch against tools.analyzer (https://clojure.atlassian.net/plugins/servlet/mobile?originPath=%2Fbrowse%2FTANAL-130#issue/TANAL-130) which should speed things up a bit.
I hit Eastwood on every (refresh)
(asynchronously), so I'd be happy to check out the speedup!
Perhaps the improvent can be offered in this fashion https://github.com/technomancy/leiningen/blob/4c601033354640aefa0bdf5c09bdd3646ff5e80c/sample.project.clj#L358
I use Lein to manage my deps but I run Eastwood as a plan lib, integrated w/ refresh
and reset
Ok, was asking since if you used deps, you could have tried out the latest commits on master now.
This is what I get on our project:
== Linting done in 386103 ms ==
real 7m22.211s
user 8m40.180s
sys 0m9.512s
== Linting done in 253887 ms ==
real 5m4.637s
user 6m27.659s
sys 0m8.197s
Hi I basically have a tree structure like this:
(def tree
[:a :b :c
[[:d
[[:e]
[:h :i]
[:y :z]]]
[:f :g]
[:q :x]]])
Now I want to find all paths to the leaves in this tree:
[[:a :b :c :d :e]
[:a :b :c :d :h :i]
[:a :b :c :d :y :z]
[:a :b :c :f :g]
[:a :b :c :q :x]]
What is a good way to accomplish this?I struggled with this, here’s my answer to my own question and a bunch of other ways to work with trees in the other answers: https://stackoverflow.com/questions/59515105/how-to-calculate-the-sum-of-all-depths-in-a-tree-using-basic-recur/59519407#59519407
You could modify mine to have not just the current branches under consideration in branches
but the full path to get there from root instead.
Thanks!
Haha I recognize some aoc there
I don’t really see how to modify that code to get the paths instead of the depths
Should keep the path so far instead of the counter or something
Not sure if that’s possible. I’ll look again after sleep
Drop both the counters, which are irrelevant to you.
And branches will contain all the nodes at a certain level, say: ["B", "G"]
and then go to the next level.
(My tree may be off)
But it should have something then such as: [["COM", "B"], ["COM", "G"]]
and at the next level it replaces the first list with ["COM", "B", "C"]
. Something like that.
I could also be off.
Anyways, you probably just want to keep track of the path as you traverse the tree until you reach a leaf
(def tree
[:a
[[:b
[[:c
[[:d
[:e
[:h [:i]]
[:y [:z]]]]
[:f [:g]]
[:q [:x]]]]]]]])
(defn find-paths
([node]
(find-paths node [] []))
([node paths path]
(if (vector? node)
(into []
(mapcat
(fn [child-node]
(find-paths child-node
paths
(conj path (first node)))))
(second node))
(->> (conj path node)
(conj paths)))))
(find-paths tree)
🙂 thanks a lot! Changing the data structure helps to make the recursion more understandable. :a :b :c
is indeed the first nodes. 🙂
Any reason transients don’t support first
peek
or empty?
? The docs say:
Transients support the read-only interface of the source, i.e. you can call nth, get, count and fn-call a transient vector, just like a persistent vector.
Which implies they should…It could be simply that implementing the necessary APIs for those operations on transient Java objects was overlooked. I looked through Clojure tickets in JIRA, and didn't notice any issues asking about that (but did find a dozen or so issues related to transients that have been fixed years ago).
There is a long historical debate about how many ops transients should support. They intentionally do not support all of them
I’m getting the impression that the scope of using them is much smaller than I initially expected
https://clojure.atlassian.net/browse/CLJ-1872 is the ticket about implementing empty? on transients
Transients tend not to remain transients for long
The goal of using transients should be to get to a persistent data structure, not to do a bunch of compute using transients
https://github.com/Folcon/delaunator-cljc/blob/master/src/cljc/delaunator_cljc/delaunay.cljc#L408
Well how far I can go is highly dependant on how flexible transients are… Ultimately there are a lot of assoc’s happening from line 423 to 425.
I originally was trying to use transient and persist at the level of the state
on line 410.
If the lookups can be done in a persistent version that isn't "the most up to date", you can do that, of course, but you are probably only asking because you need the lookup results from the latest modified version at the time of the lookup.
but it looks like I should perhaps split out :hull-tri
and :hull-next
in the loop recur
It is canonical. The official docs do contain edges/corner cases that could stand improvement in a few places.
Depending upon how important time optimizations are for the code in question to you, remember that Java is Clojure's in-line assembler 🙂
Back to your original question, first
will not work on transients because it needs a read only seq on the vec/map
I can’t quite do that @andy.fingerhut, I’m trying to keep the code cross platform. So any java I write, comes with writing an equivalent javascript…
Understood. Yeah, I forgot the .cljc suffix on your source file.
It does seem like doing this sort of thing is still rather clunky… Really want to get to the write once run anywhere =)…
You have the write once run anywhere, now you want to add "and even faster" on top
Those goals aren't always in tension/odds with each other, but certainly often are.
nth
appears to work on transient vectors, so you can use index 0 and count-1 to emulate first
and peek
on transient vectors, at least.
I feel a table for operations that work vs. do not on transients in my future ...
is there a way to get bulk archives of https://clojurians-log.clojureverse.org/ ?
Probably, but I don't know what it is. I did notice in their demo data that they say they do not offer the full logs publicly, so that they do not make it trivial for those with ill intent to mine the data.
I found that text here: https://github.com/clojureverse/clojurians-log-demo-data
If you're after the messages via an API, see if Zulip would allow that since many channels here are mirrored to http://clojurians.zulipchat.com