This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-04
Channels
- # announcements (4)
- # beginners (110)
- # boot (6)
- # calva (23)
- # cider (14)
- # cljdoc (5)
- # cljs-dev (50)
- # cljsrn (3)
- # clojure (105)
- # clojure-europe (3)
- # clojure-italy (46)
- # clojure-nl (6)
- # clojure-spec (19)
- # clojure-sweden (1)
- # clojure-uk (78)
- # clojurescript (66)
- # core-async (5)
- # cursive (19)
- # data-science (16)
- # datomic (3)
- # events (2)
- # fulcro (11)
- # hoplon (53)
- # jobs (4)
- # jobs-discuss (6)
- # keechma (51)
- # leiningen (3)
- # nrepl (25)
- # off-topic (95)
- # parinfer (8)
- # precept (1)
- # reitit (61)
- # remote-jobs (1)
- # rewrite-clj (75)
- # ring-swagger (2)
- # robots (3)
- # shadow-cljs (43)
- # tools-deps (28)
- # vim (2)
Anyone familiar with getting spurious No such var
errors?
Might have to do with Clojure 1.10+ error reporting
Hard to verify since this project uses 1.10+ fearures, so I can't tentatively downgrade so easily
doesn't sound familiar to me re 1.10 error reporting
known-good code/project is compiling fine on:
1.10.0
1.10.1-beta2
and failing with [org.clojure/clojure "1.10.1-RC1"]
, 100% of the times
it also is failing occasionally with 1.10.0
/ 1.10.1-beta2 with the same error, but I can't find what causes it
stacktrace doesn't appear to say much: https://gist.githubusercontent.com/vemv/3fd022882c9b2533fb3d669df8bcfc48/raw/56a711137778b25f6c1710721c2b9b8c4ce016ff/gistfile1.txt
project will be open-sourced soon. TODOed to provide a repro
RC1 is identical to beta2 (other than updating the changelog)
Thanks. Now I have found the true culprit: updating a certain dependency. But still I don't know the cause of the error at all, and the reporting from the compiler side is wrong, that seems for sure.
this is in the compiler analyzer, when trying to analyze a symbol in a form
to get here, it's a qualified symbol, the namespace is found (here, sut), but when it looks up the var, there is no such var in the ns
if it's failing sporadically, you may be fighting a concurrent load issue with the namespace where it is in the process of loading
I've seen something like this with spec gen where it dynaloads test.check.generators - if you've got two threads potentially loading the same namespace at the same time, you can get spurious errors like this
why do you think the reporting is wrong?
Thanks for the analysis!
FWIW I could find https://github.com/benfb/gorilla-repl/issues/10 which seems similar (:compile-syntax-check + no such var
).
In my repro I don't use a special Lein, any profiles, etc. It also fails in our CircleCI which is a vanilla one
The concurrent loading thing seems possible (although I have 0 dynamic loading)
> why do you think the reporting is wrong?
First and formost because the var is there, the ns form is correct, etc. It's known-good code, used in various projects.
Upgrading an unrelated tiny dependency (which in fact is only used in test code!) triggered the error.
And the reported error does not include the name of this dependency at all. That makes me think the reporter is wrong - a correct one would point in the direction of the dependency, rather than suggesting that the main project has an undefined var
repro? fuller msg? environment?
is there a way to tell leiningen to have a profile which ignore some files in src
and dependencies?
Hello guys, anyone familiar with clojure machine-head? Trying to connect to Azure Iot Hub, but getting this error: Execution error (EOFException) at java.io.DataInputStream/readByte (DataInputStream.java:267).
Hi! Say I intentionally throw
during testing but donβt want the stacktrace in the test output is that possible somehow (w/ lein test
/`clojure.test`)? hope that makes sense?
There's (is (thrown? ArithmeticException (/ 1 0)))
and
(is (thrown-with-msg? ArithmeticException #"Divide by zero"
(/ 1 0)))
as part of clojure.test
. Mentioned here https://clojure.github.io/clojure/clojure.test-api.htmlIs there a guide or tutorial or some kind of explanation to why we should use seq
for non-empty checks? I feel like I'm missing something, because semantics of (not (empty? ...))
are clear, and semantics of seq
requires deep knowledge of it's behavior and truthiness semantics... Which I know, but don't understand why it is advertised as preferred approach. I also remember there where some discussions on slack awhile ago where Alex Miller suggested to use nils instead of empty vectors, and just use (when xs ...)
, and I'm interested to know why is this approach considered better, because without this check you might get surprising behavior when conjing will add to beginning instead of end
I kinda agree. I saw that @ghadi mentioned that empty?
might get a counted check in the future in which case (not (empty?
will be necessary again. It feels like seq
is kinda using the implementation details of empty?
empty?
is defined as (not (seq ..))
now so the common convention for "not-empty?" is just seq
. My point is that this is true because we know the implementation of empty
. In the future, if empty?
were to be optimized by checking ICounted
the idiom of just using seq
would both miss the optimization of empty?
and not have an obvious semantic as "not-empty?" any longer
it's not intended as an optimization, but something so that empty? can work on transients
that seems to argue in favor of using (not (empty? ..
on transients then if the standard idiom seq
is not sufficient?
sorry had work. But that's why seq
as a dual to empty?
is a poor fit when empty?
is updated to work on transients but its dual would not work, right?
the reason that (seq x)
is preferred over (not (empty? x))
is because empty?
is implemented as (not (seq x))
so (not (empty? x))
is just (not (not (seq x)))
right. which was my point about implementation details leaking out. When empty? gets more complicated looking at ICounted
then using implementation details is bad, no?
@vlaaad yeah, I don't really either
I just know that's a reason that is often given
http://clojure-log.n01se.net/date/2009-02-19.html#10:24a has some discussion that rich eventually jumps into
my suggestion to @vlaaad earlier is primarily due to the use case in that context - the stuff he is doing is collection stuff. In that case, lean on nil and polymorphic collection fns and avoid using empty collections at all. If you're in more of a seq context, then lean on seq.
in general in Clojure avoid making stuff to hold a "place" - if you do that Clojure's design will lead you to code that is simultaneously easier to read, has fewer branches, and is more performant.
this applies to putting nil values in maps (just omit), making empty collections (conj or assoc into nil instead), etc
if you are working with collections (not sequences), forcing a seq just to check emptiness is not efficient
the advice to use (seq x) as a terminating predicate is primarily of use when working with sequences, where you are going to force the sequence anyways to walk it (and sequences cache that so the additive cost is negligible)
that is all my own internalized "best practice", so not trying to speak for Rich in any way here, fyi
I understand what you say about advising to use (seq x)
where I am going to force sequence anyway, but can you elaborate more on "avoid making stuff to hold a place"? Is (let [x (blah->possibly-empty-vec blah)] (when-not (empty? x) ...))
somehow a place and (let [x (blah->non-empty-vec-or-nil blah)] (when x ...))
is not?
I also worry about conjing into nil: I'd usually prefer to work on vectors, not lists, and conjing into nil produces a list
ah right, I actually was thinking of (conj) for that one
of those two examples you give, I definitely prefer the latter
wouldn't you rather avoid constructing an empty vector (which takes time and consumes memory) and also write (when x ...)
vs writing (when-not (empty? x) ...)
?
I've seen a lot of code that contorts itself to use empty?
because it's perceived as more literate than seq
-- but seq
is a fundamental function and idiom, not some advanced feature
identical?
does not work on vectors -- it happens that the compiler interns the empty vector
Clojure rewards you again and again for not making stuff. nils are cool. I like nils. I disagree with Hoare. :)
if you're going to write stuff like (when x ...)
though, you are committing to a philosophy and it requires some amount of discipline to return nil
and not []
I am all in on that
but make sure everyone in your team agrees ;)
same thing on omitting attributes from maps when the value is nil
if you're taking that approach (again, I'm all in), then you need to be careful to avoid adding those attributes when you create the maps in the first place
and aware of external libs/systems that might give you maps like that
generally, I think it's rarely worth stripping stuff out of maps if you get them from someone else
@ghadi Agree on seq
being fundamental idiom, but empty?
is still more literate, and a function to check if coll is empty in clojure core seems pretty fundamental as well, I don't see an argument here in favor of seq
these are functions that apply in different worlds
I always prefer an empty collection over a nil
. Also, I wrote my own function (not-empty? x)
For example, clojure.java.jdbc
will give you maps with nil
values if the column in the database was null
. But in next.jdbc
, at least on master, there's next.jdbc.optional/as-maps
that will give you maps where nil
values are omitted.
in some sense, jdbc is just surfacing sql here, so it makes total sense
(the default as-maps
is still nil
values from null
columns)
sql nulls are inherently overloaded
@vlaaad if you are writing seq-oriented code (using ->>, map, filter, etc), seq makes total sense and I think the language designer has been quite clear that it is the proper idiom for checking whether the seq has at least one element or not
I usually use transducers instead of lazy sequences wherever I can for performance reasons
transducers aren't always faster
hmm, I thought they are, with exception of mapcat fully realizing intermediate steps...
past blathering on this topic recorded here: https://clojure.org/guides/faq#transducers_vs_seqs
if you're only going to use 5 values, then it's a lot faster to use lazy seqs
it's not?
(criterium.core/quick-bench
(into []
(comp
(map inc)
(filter odd?))
[0 1 2 3 4 5 6 7 8 9]))
;; Execution time mean : 329.302467 ns
(criterium.core/quick-bench
(->> [0 1 2 3 4 5 6 7 8 9]
(map inc)
(filter odd?)
doall))
;; Execution time mean : 893.769899 ns
but you're forcing the seq realization to compute all values
my point is, if you don't need all of them, it can be much faster
it also depends how big your colls are and how many transformations you're doing. transducers win more with bigger colls and more transformations. the majority of code like this uses small colls and 1-2 transformations.
and in those cases, it literally doesn't matter
so write the version that's easier to read
but in example above, with a small coll and 1-2 transformations, transducers are almost 3 times faster, why it doesn't matter?
well, it's a good point that real performance issues are not what you think they are, but isn't it a death by a thousand cuts if through all your application you add extra time here and there on every coll operation?
"3 times" sounds really different but we're talking nanoseconds
so you can pay that a million times before it's 1 second different
so really more like death by 100 million cuts to care
could easily be written as a transducer, but the typical size of "merge-deps" is 3 and I much prefer the way this reads
lazy seqs are not inherently bad, don't be afraid of them :)
@vlaaad btw. I've run the same experiment you did (3x each measurement) and got much smaller difference: 570 ns for transducers and 720ns for lazy seqs
`
Just another point how misleading microbenchmarks results may be.
it's not?
(criterium.core/quick-bench
(into []
(comp
(map inc)
(filter odd?))
[0 1 2 3 4 5 6 7 8 9]))
;; Execution time mean : 329.302467 ns
(criterium.core/quick-bench
(->> [0 1 2 3 4 5 6 7 8 9]
(map inc)
(filter odd?)
doall))
;; Execution time mean : 893.769899 ns