This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-12-03
Channels
- # adventofcode (107)
- # announcements (1)
- # asami (14)
- # babashka (67)
- # beginners (89)
- # calva (34)
- # cider (17)
- # clj-kondo (5)
- # cljs-dev (2)
- # clojure (57)
- # clojure-europe (52)
- # clojure-india (1)
- # clojure-italy (1)
- # clojure-losangeles (2)
- # clojure-nl (6)
- # clojure-uk (39)
- # clojurescript (40)
- # community-development (3)
- # conjure (3)
- # cursive (17)
- # datomic (11)
- # docker (13)
- # events (3)
- # figwheel-main (3)
- # fulcro (12)
- # graalvm (7)
- # holy-lambda (7)
- # honeysql (9)
- # introduce-yourself (5)
- # malli (9)
- # minecraft (3)
- # missionary (21)
- # nextjournal (7)
- # off-topic (52)
- # pathom (3)
- # polylith (11)
- # portal (3)
- # re-frame (21)
- # reagent (34)
- # reclojure (7)
- # reitit (1)
- # reveal (11)
- # shadow-cljs (68)
- # tools-build (12)
- # tools-deps (5)
- # vim (4)
- # xtdb (9)
Something I just got hit with, I made a bad assumption. What would you think should be the result of calling a function Average() on an empty list of integers? I, mistakenly, assumed it was 0. In reality it throws an exception. My colleague said that he would have expected the exception. What do you think? 0 or exception?
I would expect an exception, or nil, or some other error result. The average function doesn't have an identity value.
Exception! If average is sum(xs)/count(xs)
then it's in the same category as dividing by zero.
Exception for sure. It would be up to the UI in a particular domain to decide to display 0 or “n/a” or other visualization.
In a language like Scala you might use an “Option” here, and for any aggregate that is not defined for multiple items
Or you make a special “nothing” object which is basically the same idea
For it to be defined, you need to be able to combine the “nothing” average with an existing average and get the existing thing back out
I could see NaN
here instead of a divide by zero exception, since 0/0
is NaN
.
I'd treat the empty list as impurity and forbid it at the edges Technically Average() could throw something like an AssertionError in dev/test, and let it be undefined behavior in prod
Can you set it up such that the empty list won't even reach the average function?
My problem is I'm querying a db table on a remote machine that logs requests and responses for a system, and I have to send back a value for the average duration between a number of requests and responses. This is to help identify when the service is running slow. I take the average and it gets floored, so an average of zero is good, means the request > response is < 1 sec. However, if there are no requests found at all, then the list will be empty. An average of zero here is bad, as there is something wrong if there are no requests. SO I think I need to send back something like -1 if its empty list to indicate error, but I'm thinking in the future would we ever want an average of averages ? This seems like this number would be nonsense. I could also send back an average and count, and then they can see if Average is zero and count is zero, then to trigger an error.
You might, but often this sort of aggregation is done in error rather than intentionally.
True, but I also wouldn't want averages, but percentiles. If you want to take the clojury approach then the average of nothing is nothing, i.e. return nil and let the recipient figure it out
Better than percentiles, you actually want the histogram. Just looking at key percentiles throws away a LOT of data. (granularity of the histogram is an interesting topic, but the idea is the same: Retain your data when aggregating)
Agree, raw data is best, but in a choice between average and a list of percentiles, I prefer the latter
Oh certainly agreed, a list of percentiles (ie. a histogram 😉 ) is very useful for understanding the shape of a data set (ie. the distribution). Average does have its uses though, in that it doesn’t throw away any data, whereas a single percentile throws away most of it. For latency tracking, a “trimmed mean” is often a really good statistic, as it has the benefits of Average (single number to interpret, not throwing away most of the data), but also deals w/ the most common problem with averages: Outliers.
Yes, it is often the case that these are what get looked at, though I think that is more of a tooling artifact than being driven by our goals. Usually we want to go faster for everyone, not just those that happen to feel these percentiles. From my observations, looking at specific percentiles tends to cause the latency histogram to have “bumps” and consolidate just below these signposts, primarily because latency improvements for requests in the faster 50% of the population don’t get “counted” when we look at what changes moved the needle. Don’t get me wrong, any attention to latency is good, but I think we can do better than just a handful of percentiles
"it depends" Maybe I'm spoiled by Gil Tene's talks on latency, but in certain scales those percentiles are a real pain, I care about the high percentiles, to an extent where I don't care about the bumps as much as I care about the tail in plenty of circumstances
An average of averages is a weighted average
I would say that if you have no data, then you have no average. It's simply not defined, and using a special value within the space of numbers to indicate that is a bit of a kludge. So, yeah, nil seems the way to go. Or some kind of special non-numeric sentinel value, or an empty option, or an omitted field, or whatever else makes sense for the communication language
On the idea of using -1 or 0, consider what will happen if you start wanting to report a metric where negative numbers or zero are actually valid. Well crap, now you've got to figure out some other approach for that metric, and then your system will have inconsistent and confusing semantics
Any users of Nix want to share experience and tips on setting it up for clojure development. Thinking in particular about pinning java versions per repository, etc instead of using jenv
I’m only getting started with Nix myself, but w/ my limited knowledge I’d use a shell.nix
in the project’s directory. I’m currently trying https://github.com/nix-community/lorri to keep the current shell up-to-date wrt shell.nix
.
It looks like the https://github.com/NixOS/nixpkgs/blob/nixos-20.09/pkgs/development/interpreters/clojure/default.nix uses JDK11 for the clojure
/`clj` commands.
I created a new repo on GitHub and selected Clojure
for the .gitignore
. It used this file https://github.com/github/gitignore/blob/218a941be92679ce67d0484547e3e142b2f5f6f0/Leiningen.gitignore
My editor is Calva and I'm doing a deps.edn
project.
This file https://github.com/github/gitignore/blob/218a941be92679ce67d0484547e3e142b2f5f6f0/Clojure.gitignore suggests that I should make a new file and reference it for deps.edn
projects.
Anybody have a different/better idea?
Same, but if there's a template I'd like it to be generally useful.
I added
# Calva
.calva/
.clj-kondo/
.lsp/
sure. that template looks geared towards the stuff that lein makes so it doesn’t seem that useful to me
i think you want to ignore .clj-kondo/.cache and .lsp/.cache . Both of those directories can have useful stuff you want checked in
that was such a confusing message. you want to ignore .clj-kondo/.cache. not just the root .clj-kondo since there are useful config files in there
here are my additions at this point
# Calva
.calva/output-window/
.clj-kondo/.cache/
.lsp/.cache/
thanks for the tips!
If you haven't already, you should check out Gibo https://github.com/simonwhitaker/gibo for gitignore boilerplates. Starting up a project I do gibo dump clojure > .gitignore
and get
pom.xml
pom.xml.asc
*.jar
*.class
/lib/
/classes/
/target/
/checkouts/
.lein-deps-sum
.lein-repl-history
.lein-plugins/
.lein-failures
.nrepl-port
.cpcache/
I often use the the gitignore file generated by this site: https://gitignore.io/
If you create a Clojure project with deps-new
, you get this https://github.com/seancorfield/deps-new/blob/develop/resources/org/corfield/new/app/root/.gitignore (it's the same for a lib
)
Trying to find a reference from @alexmiller about multiple :require
in one ns form not being supported/idiomatic. Should be easy now that we have history here on Slack... I think it came up in relation to the new :as-alias
. Trying to find "evidence" in relation to this issue. https://github.com/clj-kondo/clj-kondo/issues/792
Interestingly enough, it's straight up an error in CLJS: https://clojure.atlassian.net/browse/CLJS-254
https://groups.google.com/g/clojure-dev/c/6EEfdPhrWgk - no definitive answers, but some opinions from well known people.
Ah, found it, by Alex Miller: https://clojurians-log.clojureverse.org/clojure/2020-07-27/1595872486.471000 Where the linked article by Stuart Sierra says: > Use each clause at most once.