This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-20
Channels
- # announcements (8)
- # babashka (19)
- # beginners (100)
- # boot (3)
- # calva (16)
- # cider (8)
- # cljdoc (6)
- # cljsrn (15)
- # clojure (73)
- # clojure-europe (7)
- # clojure-france (1)
- # clojure-italy (12)
- # clojure-nl (11)
- # clojure-sg (1)
- # clojure-uk (17)
- # clojurescript (63)
- # cursive (22)
- # data-science (2)
- # datomic (2)
- # defnpodcast (1)
- # docs (1)
- # fulcro (7)
- # graalvm (8)
- # jackdaw (1)
- # kaocha (11)
- # off-topic (26)
- # pedestal (4)
- # planck (1)
- # re-frame (35)
- # reitit (5)
- # ring (3)
- # shadow-cljs (25)
- # slack-help (11)
- # spacemacs (8)
- # specter (2)
- # tools-deps (61)
- # vscode (6)
- # xtdb (3)
2 seemingly simple questions:
1. Why is ({:a 1} :a)
faster than (:a {:a 1})
?
2. Per the documentation, the =
operator dispatches to equals
function of the concrete class. That being the case, why is (= "a" a)
much slower than (.equals "a" a)
(when a is (def a "a")
clojure.core/=
only dispatches to equals
of the concrete class as a last resort, after checking several other cases.
If you look at the source code for clojure.core/=
you see it calls this Java method, assuming we are talking about Clojure/Java, not ClojureScript: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Util.java#L24-L36
What method did you use to measure the relative speed of ({:a 1} :a)
and (:a {:a 1})
? Realize that microbenchmarks like that can be a bit challenging to get useful performance results from, given how short they are, JIT compilation on the JVM, various JVM options that can modify JIT behavior, etc. Criterium is a good library to use for as stable of results as people know how to achieve: https://github.com/hugoduncan/criterium
Huh, that defrecord thing surprises me a bit, but I use defrecord so rarely that I probably would not have noticed.
Also one surprising thing: (:x foo :default)
does not return :default
when :x
is nil in the defrecord foo
Thanks a lot guys!!!
Are pre- and postconditions not available for fn
, only for defn
? I tried to add a {:post [...]}
block to an fn with a spec2 check, but it seems like it gets ignored completely
should work on fn
https://clojure.org/reference/special_forms#_fn_name_param_condition_map_expr
prepost map goes after the arglist - is that where you have it?
Seems to work, this gives an assertion failure:
((fn [x] {:post [(= % 1)]} (inc x)) 2)
user=> (def f (fn [i] {:post [(int? %)]} (if (odd? i) (str i) i)))
#'user/f
user=> (f 1)
Execution error (AssertionError) at user/f (REPL:1).
Assert failed: (int? %)
user=> (f 2)
2
it's easy to forget the vector in :post too
Hm I had the vector... Maybe a spec2 problem? I'll test some more, and if I run into something I'll report
Hi everyone. Anyone know how to stop clojure truncating tracebacks? I'm doing a lein test
and getting a traceback ending in ... 102 more
. How do I see those 102 more?
the 102 more are repeated in one of the other nested exception stack traces (so you are likely actually seeing those elsewhere already)
Hmm what was that again when I get a "No matching ctor found for class" for a function?
That means Java was trying to construct a class, and it couldn’t find a constructor that takes the types of arguments you gave it.
in the example above s/fn
is an invalid option, but I'm looking for something that would do it, to describe that the function returns a function
I’ve been out of the loop a bit, so I’d like to ask if Luminus is still one of the best out-of-the-box template/framework options for Clojure.
As an offshoot of that question about Luminus, for folks who are exploring the built in deps/cli tools over leiningen, will something like https://github.com/seancorfield/clj-new be able to create similar full stack, composable templates like Luminus?
Hmmm, it actually looks like you can create the actual preexisting Luminus templates with this clj-new tool?
Yes, clj-new
can execute Leiningen templates (and Boot templates), as well as newer clj-template
templates. If you find one that won't run, it's a bug and I'll (try to) fix it. Also, be aware that if clj-new
runs a Leiningen template, it's not magically going to produce a deps.edn
file -- it'll be a project.clj
-based project!
I see. So I would be looking to create a bespoke template with clj-new that mirrors the Luminus ones if I wanted the same structure?
You could just run clj -A:new luminus chasote/webapp
and then create an appropriate deps.edn
based on whatever ends up in project.clj
.
The :dependencies
vector would become the main :deps
entry and then each profile would become an alias -- but you'd have to figure out the equivalent to Leiningen plugins yourself.
I'm not entirely sold on moving over yet but so far I like the deps tools and have been switching my editor integration to also take advantage of the built in socket (p)repl tools too (I'm using neovim/conjure). It's not quite ready yet (shadow-cljs doesn't work with the prepl) so I'm also trying to convert a shadow-cljs project to figwheel-main (which does work) which has been difficult.
Yeah, I use Atom (since 2015? When I switched away from Emacs) and ProtoREPL is no longer maintained so I switched to Chlorine which works with a Socket REPL.
So now I can use Atom/Chlorine locally and also on any remote process started with a Socket REPL JVM option.
No nREPL, no Compliment. Just out-of-the-box Clojure.
I don't do any ClojureScript -- I suspect that's the area where deps.edn
is weak in comparison to lein
-based or shadow
-based tooling.
Yep, which is a strong interest of mine so I think I might be switching too early. Just as a thanks though, know that one motivation for gravitating towards certain tooling is if you are actually involved because I've seen how helpful you are on here.
One day I may go back to ClojureScript -- we last tried it in 2014/2015 and it wasn't really ready for primetime back then. Tooling (and the core language itself) has improved dramatically since then.
But just to confirm, luminus is still a prime contender for framework/template for Clojure these days?
@U061KMSM7 I think the answer to that is subjective. I've never used the Luminus template (except as a test case for clj-new
🙂 ). I don't particularly like some of the libraries it bundles in and I don't much care for the structure of the basic project it creates. And of course I don't use Leiningen these days. But I know there are folks who seem to like the somewhat "batteries-included" approach of Luminus.
Any other alternatives you would recommend?
Or particular libraries you would swap out?
I prefer to start from scratch and only add in the libraries I actually need. These days that's going to be Component, Ring, Compojure. Almost certainly next.jdbc. Then it will depend on what I'm building.
https://github.com/juxt/edge seems a fair contender for "deps-based web template"
I'd say that's probably more opinionated than Luminus -- and depends on some far less widely used libraries (such as Juxt's fork of Aleph -- and Aleph itself is pretty niche) -- so it really depends on whether you buy into those libraries.
These templates are fine if you understand what you're getting yourself into. The Juxt folks are very supportive, so you'll get plenty of help if you buy into their stack but if you decide to use New Relic for production monitoring and metrics, I wouldn't be surprised if Aleph is poorly supported by it (http-kit is not well supported, for example, which was why we switched back to Jetty).
Yes, clj-new
can execute Leiningen templates (and Boot templates), as well as newer clj-template
templates. If you find one that won't run, it's a bug and I'll (try to) fix it. Also, be aware that if clj-new
runs a Leiningen template, it's not magically going to produce a deps.edn
file -- it'll be a project.clj
-based project!
:handler (-> (new-middleware {:middleware [not-found-handler
[fulcro-wrap-api :component]
fulcro-server/wrap-transit-params
fulcro-server/wrap-transit-response
[wrap-resource "public"]
wrap-content-type]})
(component/using [:datomic-db]))
:wires-http-server (component/using (new-http-kit :port (config :dev :wires-http-port))
{:handler :handler})]
Unfortunately, component/using
within wires-http-server
does not work as expected. Look at this trace:
(reset)
TRACE t51411: (system.components.http-kit/new-http-kit :port 3000)
TRACE t51411: => #system.components.http_kit.WebServer{:options {:port 3000}, :server nil, :handler nil}
Execution error (NullPointerException) at system.components.http_kit.WebServer/start (http_kit.clj:11).
null
oh, I bet reset is starting your system and one of your components has a bad stop behavior which causes it to not restart correctly
The problem is that :handler
in new-http-kit
call is not updated with component/using
there's an example here https://github.com/danielsz/system-dependency-injection/blob/d9427bf34be843b187d3dce97ea8afaface17e80/src/example/systems.clj#L22-L35
I ended up creating my own components for simple use cases like this, where you have a clear separation between the server and handler component
something like this: https://github.com/nomnom-insights/nomnom.duckula/blob/master/dev-resources/duckula/test/component/http_server.clj (uses jetty component, but it shouldn't matter)