This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-13
Channels
- # announcements (1)
- # babashka (30)
- # beginners (43)
- # biff (24)
- # calva (72)
- # cider (12)
- # clj-commons (24)
- # clj-on-windows (10)
- # cljsrn (23)
- # clojure (123)
- # clojure-bay-area (6)
- # clojure-europe (43)
- # clojure-losangeles (2)
- # clojure-nl (2)
- # clojure-uk (9)
- # clojurescript (125)
- # core-async (9)
- # cursive (2)
- # data-science (3)
- # datomic (30)
- # devops (1)
- # emacs (13)
- # events (5)
- # fulcro (15)
- # graalvm (3)
- # gratitude (1)
- # humbleui (11)
- # lsp (5)
- # nbb (24)
- # off-topic (11)
- # pedestal (5)
- # releases (1)
- # remote-jobs (1)
- # sci (15)
- # scittle (16)
- # shadow-cljs (15)
- # sql (11)
- # tools-deps (9)
- # xtdb (5)
Just found an interesting difference between JDK 18 and JDK 19 that affected Clojure/Java interop for us: (Thread/sleep (computed value))
may now be a reflective call and needs a type hint -- in JDK 19, Thread/sleep
now has an additional overload that accepts Duration
.
"Luckily", we have (set! *warn-on-reflection* true)
in every (non-test) namespace so we caught it in CI. We had 30 such calls across our whole codebase. Calls like (Thread/sleep (* 1000 60 60))
are still fine.
Interesting! Sean, I’m sure you know this, but I’m finding https://github.com/jonase/eastwood is helpful in reporting on reflections (among other things).
@U0LAJQLQ1 ^Long
works.
It's only a performance problem, but if you have short-duration sleeps that could make a huge difference.
The other issue with this that I think most people don't pay much attention to is if you're calling sleep on an OS thread and not a virtual thread, very small sleep times are not precise. Schedulers can make a thread sleep for 5 ms minimum when the thread is marked high priority up to 20 ms on windows, and 15 ms on linux.
(I need to double-check those numbers, I researched this a while back while writing a game loop, but those numbers should be in the right ballpark)
If you need relatively high precision on short sleep times you need to spin pretty much.
Not just performance. Without the type hint there were some calls Clojure could no longer resolve at all - the code wouldn't compile.
ah, that's good to know, although surprising. Were there previously casts that were happening implicitly as invoke
was called?
That was what alerted me, when CI failed on 19. So I ran a full reflection checker to make sure all such calls got fixed. But it was a surprising change since sleep
has been around and unchanged for so long - and I was expecting more obvious differences to pop up (but that's been the only one we've found so far).
Presumably, yes, Clojure was inserting casts but not needing reflection.
Or at least adding unboxing calls.
Could someone please explain what "reflective call" means in this context? (I'm familiar with reflection in java, but not in clojure)
if you understand it in java you're 90% of the way there. In Clojure if it can't tell with 100% certainty the exact method you're going to be calling at compile time (maybe because it doesn't know what class it's on, or the method has multiple overloads), then it generates code that looks at the object with java reflection to then try to call the method.
You can help Clojure be sure about what method is being called by adding type hints.
You can tell if Clojure is generating reflection if you put
(set! *warn-on-reflection* true)
in your file after the ns form.Hello! I've grown a little reagent/re-frame app that has no backend over the last couple of months and I'm at a point where I'm considering moving into backend territory. In my day job I'm a UI dev and I have literally no experiences with databases. Is there a good tutorial or book that I can use to get started with both backend and database development?
how about https://pragprog.com/titles/dswdcloj3/web-development-with-clojure-third-edition/ ?
I understand https://www.amazon.co.uk/Web-Development-Clojure-Dmitri-Sotnikov/dp/168050682X/ref=sr_1_fkmr1_1?keywords=clojure+web+dev&qid=1665652543&sr=8-1-fkmr1 is good
are there any tools for showing dependencies in the source code on a graph view? like static analysis drawing a graph of functions calling other functions - to visualize stuff like:
(defn x [a] a)
(defn y [a] (x a))
(defn a [a] (+ (x a) (y a)))
=> {x nil y [x] a [x y]}
Plenty, some are more fitting than others: • https://github.com/jpmonettas/clograms • https://gitlab.com/200ok/codegraph • https://github.com/gfredericks/clj-usage-graph • https://github.com/benedekfazekas/morpheus • https://github.com/testedminds/lein-topology • https://github.com/hilverd/lein-ns-dep-graph • https://github.com/SevereOverfl0w/vizns • https://github.com/hiredman/clojure-dependency-grapher
https://github.com/benedekfazekas/morpheus makes use of clj-kondo static analysis to do so: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md
Not all of the options @U2FRKM4TW mentioned do function <-> function dependencies though (but most of them do?)
why so few stars, seems like super handy tools for large codebases? (I usually have a baseline that super useful libs in clj get ~500-1k)
Personally, I have never had a use-case for those. But maybe I do have use-cases and I just prefer to use stuff that's built into my IDE and I "simulate" those libraries basically in my brain using the IDE tools.
Some tooling libraries are used only every so often, this is why they are less popular in terms of stars
Does anyone know of a Babashka-like tool that compiles to native machine code rather than running inside a vm?
GraalVM native-image
compiles JVM bytecode to machine code so it can run as a standalone binary
https://github.com/Tensegritics/ClojureDart/blob/main/doc/quick-start.md is also an option.
Thanks Borkdude, I thought GraalVM binaries were quite resource intensive as well, but I'll check out native image. Part of my motivation is to keep the executable size small and resource usage low. I don't mind running against an interpreter as long as the interpreter is lightweight and fast. Think Dash over Node.JS or JVM. Thanks for the ClojureDart suggestion, Evan. I'll check that as well
@UVDD67FFX GraalVM binaries are not resource intensive. E.g. bb only requires 5mb of memory to run
but if you don't mind running in an interpreter, you can use babashka as well, if your code runs with that
Dash is a lightweight Bourne Shell implementation. It's a popular alternative to Bash for shell scripts that don't use Bash-isms
If Node.js is an option, you can also use #C029PTWD3HR which is for scripting on Node.js using Clojure
> bb only requires 5mb of memory to run I know that those things don't really correspond to each other, but it's still somewhat surprising, pleasantly so, given that the binary itself is >80 MB.
The Node.js binary is around the same size and starts up fast. But bb starts faster ;)
Huh! I definitely expected the exact opposite, with me being on Linux. My intuition is heavily skewed by Docker on MacOS that at least used to run in a VM, I think. And by some MacOS tools that are vastly limited compared to their (probably differently licensed) Linux counterparts.
Binary size is a weird thing but give or take 10-15 mb they're roughly the same size
@U2FRKM4TW Linux is a mixed bag. I find the popular Desktop distros to be pretty resource intensive. I don't think they're any better than macOS in terms of performance.
Oh, I'm not arguing about that. My point was that the basic functionality in Linux tends to be better.
There's also #C03SRH97FDK which I think it's pretty incomplete, but is a native Clojure I think.
> the basic functionality in Linux tends to be better. 100% support this after 7+ years on mac and the last 3 on linux. 7 years was a lie 😛
after a bad streak of unexplained kernel panics on my xps (possibly caused by hw issue) and just tired of dealing with stability issues
I think Mavericks was the pinnacle for me. After that they just added stuff I didn't care about
The last Windows I used as a daily desktop was Windows 2000. I've been working on Linux since then, until a few years ago when I had to use a Mac for work. It was a very frustrating experience. The window manager on a Mac is terrible.
My (literal) breaking point for Macs was when i started having an infra-dev title in my job description as well, started noticing overall dev on linux is just simply better. still have to deal with a mac at work though and would give M1 speed the claps it deserves.
Maybe can try asahi linux sometime
yeah wouldnt wanna brick the work machine 😛
@U050SC7SV citing your stability issues, could recommend Fedora. running it since i switched. almost as quick updates as arch but hasnt crashed once
probably h/w issues i suppose
+ I reached the 3yo on that machine so I could get it replaced, so it was just good timing
gentle reminder of the original thread getting totally derailed. hope thats okay
i started it!
I got all I needed from the thread. Thanks to everyone who answered. I'm happy for the discussion to move onto more important things 😉
GraalVM can do both JIT and AOT compilation. So if you use it's native image feature it does AOT compilation to native, similar to Go.
If you're more looking for a packaged executable, as opposed to a compiled binary, you can check this out: https://github.com/babashka/nbb/tree/main/doc/caxa It packages an nbb script as a single executable.
Why call str
on lazy sequences triggers the evaluation of the sequence?
user=> (str (map prn [1 2 3]))
1
2
3
"clojure.lang.LazySeq@745f"
Because it should return "(nil nil nil)"
, but doesn't due to a bug: https://ask.clojure.org/index.php/12310/why-does-str-map-identity-return-clojure-lang-lazyseq-this
wild to see that marked as a bug after all this time, but that doesn't actually answer the question
• it evaluates everything, not just the first chunk • from clojure 1.0.0 up to 1.11.1, it behaves exacly the same, with same hash code in the str etc.
According to the Jira bug, the lazy seq is realized in order to compute the hash used in the string representation. (Just saying this because it wasn’t obvious to me based on the existing messages in this thread).
Pure coincidence that Alex was apparently just looking at this? from https://clojure.atlassian.net/browse/CLJ-2647 > Alex Miller updated the Summary yesterday > Revisit printing of lazy seqs → Lazy seqs do not print readably
Has anyone ever tried to serve webfonts using io/resource
? When I slurp
on it, it seems to give me an corrupted file (perhaps encoding issue?). I'm running a web app and serving resources via io/resource
and while CSS files, for example, work fine, webfonts (ttf, woff, woff2, eot) do not. By "do not work" I mean I get the file contents just fine, but when served with the corresponding mime type and all, doesn't work when visiting with the browser.
Reason I think its corrupted is because when I download a TTF via the browser, I can't open it because it says it's faulty - and yet I can open the file in resources/
just fine. Hence, I'm guessing encoding, but I'm not sure.
if you want say the contents of a file as a byte array, then you can use a ByteArrayOutputStream together with http://clojure.java.io/copy
I have my own baked solution - no ring - that already works fine with static assets, except webfonts. So that's why I'm, in particular, interesting in figuring out what's the issue there. Why slurp
doesn't work, and what would. I'm not looking to replace my entire system.
creating a string involves taking a bunch of bytes(8 bits), and interpreting as characters (actually 16 bit code points? some characters are two code points depending) using an encoding
even better for large things, don't pull them entirely into memory at all, but how to do that will depend on whatever webserver api you are working with
Yeah large things will prove to be a headache most likely, thankfully I just need webfonts which are very small. I got it working with
(io/input-stream (io/resource path))
Thank you!Any ideas why could it be that doing
clj -Sforce -Sdeps '{:deps {mount/mount {:mvn/version "0.1.16"}}}' -Stree
Downloading: mount/mount/0.1.16/mount-0.1.16.pom from clojars
Downloading: mount/mount/0.1.16/mount-0.1.16.jar from clojars
org.clojure/clojure 1.11.1
. org.clojure/spec.alpha 0.3.218
. org.clojure/core.specs.alpha 0.2.62
mount/mount 0.1.16
and then doing
cat ~/.m2/repository/mount/mount/0.1.16/mount-0.1.16.pom | grep artifactId
<artifactId>mount</artifactId>
<artifactId>clojure</artifactId>
<artifactId>clojurescript</artifactId>
<artifactId>datascript</artifactId>
<artifactId>compojure</artifactId>
<artifactId>ring-jetty-adapter</artifactId>
<artifactId>cheshire</artifactId>
<artifactId>hiccups</artifactId>
<artifactId>clojurescript</artifactId>
<artifactId>cljs-time</artifactId>
<artifactId>logback-classic</artifactId>
<artifactId>tools.logging</artifactId>
<artifactId>hooke</artifactId>
<artifactId>tools.namespace</artifactId>
<artifactId>tools.nrepl</artifactId>
<artifactId>datomic-free</artifactId>
....
So I don't understand why -Stree doesn't show them, and also no idea why mount packaged with all those deps, since they are dev dependenciesHave you checked the <scope>
of those dependencies?
It's not "packaged" with them, it just depends on them.
oh ok, they are provided, I see
deps only considers compile and runtime dependencies of Maven artifacts
makes sense
Maybe a nonsensical question, but does it make sense to exclude compile-time dependencies when building an uberjar? Or does a compile-time dependency conceptually also constitutes a runtime one?
conceptually, maybe, but in practice Clojure libs don't use compile scope dependencies, and even Java libs pretty rarely use something only at compile time and not as a runtime dep
Ah, so deps considers them just because not doing that would potentially break some libs?
better to include and let you exclude than the opposite imo
(but again, it's very rare to encounter this at all)