This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # announcements (1)
- # babashka (5)
- # beginners (64)
- # cider (9)
- # circleci (11)
- # clojure (80)
- # clojure-uk (25)
- # clojured (6)
- # clojurescript (35)
- # css (1)
- # cursive (3)
- # datomic (6)
- # fulcro (10)
- # graphql (3)
- # kaocha (2)
- # leiningen (3)
- # lumo (3)
- # malli (10)
- # meander (24)
- # off-topic (17)
- # re-frame (10)
- # reagent (2)
- # ring (1)
- # shadow-cljs (27)
- # spacemacs (3)
- # tree-sitter (3)
hello folks. i always used components and didn’t like the way components look (oo style) and watched one apropos episode where they discussed how they never used component model, I didn’t understand how can you build a server which needs a database and many more other things without component... how can you restart a server to make changes?
Or implement the kinds of start/stop functions that component encourages, using hand-written functions?
I would encourage you to examine and dig in to why you think component is oo style. It doesn't match alan kay's idea of oo "OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.", and it definitely doesn't match C++ or Java's
so you may need to step back, figure out what it is you actually don't like about component without describing it as something it isn't, and then once you have done that you will be in a better place to evaluate and determine what you want
in general, most people that don't like component use mount (several popular templates use mount), but if you don't like oo style, you will really hate mount because it keeps your state in a bunch of global singletons
that’s what i thought. i think component it’s not elegant but the best solution for developer workflow
they must evaluate all the functions on the repl and trust the router/db to do its thing
so I don't know mike or the kind of work he does, but in general I have crossed paths with him on clojurescript stuff
so my guess is he is primarily a front end guy, and primarily the role of composing a system is played by whatever front end framework he is using
I, on the other hand, never write clojurescript, avoid writing js as much as possible, and use component all the time, and heavily advocate its use
> didn’t like the way components look
this is because of
defrecord I assume?
You can also use metadata-based protocol extension, which allows you to write
stop as plain
There is also integrant - I have not used it myself but I have heard plenty of people speaking highly of it
I haven't used integrant, but I have worked on a project that monkeyed with component to make it use multimethods instead of a protocol for Lifecycle, and protocols are much nicer to deal with for creating stubs in tests, etc
Ive recently switched from component to integrant and Im loving it. Things compose much better without having to wrap everything with records. It's also easy to mock stuff: all you have to do is assoc the stub in the config map
There’s also clip. Lots of strategies for dep injection. https://github.com/juxt/clip
Is it a discussed/documented fact that the Clojure compiler is slow? I feel there's been a lot of more talk about the startup time... For example:
(inserting actual code instead of that string) informs me that we can only compile 1000-2000 tiny defns per second... Might seem enough, but in a nontrivial codebase, various categories of tooling suffer
(dotimes [_ 1000000] (time (eval (list `defn 'foo  "<Insert some trivial functionality here>"))))
There is no 'official' documentation on speed of anything, other than some constant / "effectively constant" / linear time things in doc strings. None of that for compilation speed itself. There has probably been some discussion about it occasionally spread over 10 years, but I have no links to share, if there were such discussions.
I wouldn't be surprised if there were 2x performance gains that could be had there, if you tried hard enough. Whether such changes would ever become part of the Clojure itself is much much more 'iffy'. If the core team really wants those changes, and they are trivial to review as not changing the behavior of the compiler, and they speed things up measurably on common use cases, and do not slow down anything else, then maybe, but no one will promise you that such changes will ever be looked at in your lifetime.
You can create your own personal GitHub fork of the Clojure code base with all of the experiments you want to try, and let others try, if that interests you.
> There is no 'official' documentation on speed of anything [...]
It's something I've tried to google a couple times with no luck. The ideal material I would love to find is an explanation/analysis of why a single
eval takes that much.
> You can create your own personal GitHub fork of the Clojure code base with all of the experiments you want to try, and let others try, if that interests you.
Yes, this could be a cool side project :)
Someone like bronsa has looked at this a lot, and may be willing to share what he knows on the topic. Not many people dive into the compiler a lot. Except for one's own curiosity/learning/knowledge, there isn't much benefit to doing so. I agree that those things can be big benefits.
One thing to note is that Clojure's compiler is mostly "fairly straightforward" translation of Clojure data structures into JVM byte code. i.e. unlike an optimizing compiler for C++, there is no extensive data flow analysis/etc. that runs quadratic time algorithms on the data structures representing the code, so a lot of it is pretty close to linear time in the size of the code.
You may want to do some quick benchmarks on 3 or 4 significantly different sized Clojure defn forms to check what actual measurements show.
There are some fixed overheads to calling eval, my guess is you will get very different behavior if you batch up code into
dos vs calling eval repeatedly. The typical code loading case (outside the repl) is going to behave much more like a batch job
> so a lot of it is pretty close to linear time in the size of the code. yes, this is what I've observed. I thought it was a matter of bigger defns -> more "sauce" in them. Not merely size directly related to data structures... that's interesting
There are exceptions to that "mostly close to linear time", e.g. one or both of
doseq generates code size that is exponential in the depth of the nesting, but most people don't write code that nests those deeply.
> There are some fixed overheads to calling eval
Fair one, I might play with a more representative benchmark
At the same time,
(c.t.n.repl/clear), (c.t.n.repl/refresh) should be the most practical benchmark, and it's certainly slow-ish in every project (proportional to codebase size)
I haven't looked into
case in detail, but the Clojure compiler does some compile-time hashing to create a branch table there that I do not know whether it is nearly linear time, or slower.
When I said "data structures" above, I was referring to the data structures read by the reader, of the code. Not data structures being manipulated by the program at run time.
Refresh is going to be more of the code loading you mentioned, not entirely equivalent to calling eval repeatedly
There are also at least some Clojure devs, most vocally Sean Corfield, who avoid 'reloaded' workflow completely, preferring instead to remember to evaluate any changed functions while developing
I believe primarily not because of speed (although that might be part of it), but because of not wanting to deal with the problems that sometimes arise with reloaded workflow tools (but believe his word over mine for his reasons).
Anyway my point wasn't about
refresh, but about the perceived fact that clojure compiling / code loading is slow. This seems to have multiple implications (e.g. refactor-nrepl, Eastwood, which perform code analysis based on
eval, and also
One sometimes hears from other toolchains that they can compile xxxK LOC per second. My medium-sized codebases cannot say anything like that :)
Eastwood is using tools.reader and tools.analyzer and tools.analyzer.jvm, so speeding up Clojure's compiler and reader would have 0 effect on Eastwood's speed (well, except maybe indirectly)
fwiw, I know that It'd help to understand that I'm not asking "I have problem practical x and want a solution", but "I see the x pattern of problems in various tools, is this something well-known?"
I don't think anyone advertises xxxK LOC compilation speed for Clojure. Much higher on the list would be "often significantly smaller and less complex code bases, for faster human reasoning and development speed"
where "less complex" is enabled by some of Clojure's features, but Clojure developers are free to introduce as much complexity using those features as they are willing, so there is no guarantee of achieving those benefits, of course.
> I don't think anyone advertises xxxK LOC compilation speed for Clojure. Much higher on the list would be "often significantly smaller and less complex code bases, for faster human reasoning and development speed" I agree, and also am interested in bridging the former and the latter (within reason, and with a large risk of failing) i.e. it'd kind of surprise me that if the JVM is fast, and Clojure can be fast, then code loading couldn't possibly be fast
It is virtually guaranteed that it is possible to make it faster, as nearly any code can be made faster if you work at it enough. "Programming is an economic activity", and it probably isn't on the list of the top 20 problems the Clojure core team is interested in tackling for the official Clojure compiler code. Thus it is relegated to experimentation, which for most people reduces their interest in spending much time on it.
We do periodically check that we didn’t do something stupid at least
There were some issues particularly in macro compilation that we fixed back in 1.7 or 1.8 or so
The Clojure compiler is intentionally very simple - in the broad sense it takes a Clojure expression and turns it into bytecode
Since I was invoked in this thread... speeding up c.t.n.repl would have zero impact for any workflow that I think is useful.
Could the Clojure compiler be sped up? Probably. Would it help lots of people's workflows? Maybe. Would it help any production workflows? Yeah, folks who aren't doing AOT.
So, yeah, work on speeding up the Clojure compiler is valuable as long as it doesn't change any of the semantics.
Hi All! How does one go about specifying something like Maven’s “provided” dependencies in deps.edn?
For example, what would be the idiomatic way to represent the following in deps.edn?
<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.1.0</version> <scope>provided</scope> </dependency>
@abdusalam The simple answer is "you don't". Scope makes no sense in the
deps.edn world. Either your project needs a lib or it doesn't.
Any consumer of your library can easily override your version choices by specifying their own.
that moment when you realize you've picked leap day to test date comparators 😎
(let [t1 #inst"2020-02-29T21:29:33.479-00:00" t2 #inst"2021-02-29T21:29:33.479-00:00"] (compare t1 t2)) Syntax error reading source at (REPL:2:46). failed: (<= 1 days (days-in-month months (leap-year? years)))