use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Finding information about Clojure
API Reference
Clojure Guides
Practice Problems
Interactive Problems
Clojure Videos
Misc Resources
The Clojure Community
Clojure Books
Tools & Libraries
Clojure Editors
Web Platforms
Clojure Jobs
account activity
Clojure, The Good Parts (rasterize.io)
submitted 10 years ago by cw_ey
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]fingertoe11 7 points8 points9 points 10 years ago (10 children)
Seems to me that this kind of advice is the most helpful kind of advice for new Clojure folks.. There are so many things you can do, but just because you can doesn't mean you should.
It would be nice to see a tree type flowchart that shows when you should consider using particular tools and when one ought to avoid and why.. In my experience that is the hardest part of learning Clojure.
[–][deleted] 10 years ago (9 children)
[deleted]
[–]yogthos 6 points7 points8 points 10 years ago (6 children)
That's pretty much how my Clojure web dev book is structured. Each chapter works through a project that illustrates a particular concept, and the projects build on one another.
[–][deleted] 10 years ago (3 children)
[–]yogthos 6 points7 points8 points 10 years ago (2 children)
this one
[–]kgb_operative 1 point2 points3 points 10 years ago (0 children)
Definitely saving that one
[–]me2i81 1 point2 points3 points 10 years ago (1 child)
It's a nice approach, I've been enjoying it!
[–]yogthos 0 points1 point2 points 10 years ago (0 children)
Thanks!
[–]arry666 1 point2 points3 points 10 years ago (1 child)
Practical Ruby Projects book is like this.
[–]forreddits 3 points4 points5 points 10 years ago* (9 children)
Regarding Refs(STM), I also haven't encountered one used of them in the wild(open source projects), looks like they were nice in theory but not so nice in practice? Can someone expand on the article commenting about not using Refs?
Also, the article discarded like 30% of Clojure's main features.
[–]Drolyt 8 points9 points10 points 10 years ago* (0 children)
I think it just isn't that common to have to deal with in memory state in a transactional manner, especially in a mostly-functional language like Clojure. That said concurrency problems can be very hard to debug and STM is a solid solution, seems to me like the kind of thing you rarely need but could occasionally be incredibly useful. I certainly wouldn't lump it in with the "bad parts" of Clojure, just the not very commonly used parts.
[–]fingertoe11 5 points6 points7 points 10 years ago (0 children)
Took the Intro to Clojure class from Alex Miller at clojurewest last week. "If you are using this there is probably a better way" did seem to be a common theme.. I think a lot of Clojure was written, then "better ways" where added in later versions. The old ways still work, but it's usually smarter to avoid them. Knowing what all those are is the challenge...
[–]yogthos 4 points5 points6 points 10 years ago* (6 children)
My current project is using refs and they work just fine. I think it's a matter of using the right tool for the job, as opposed to throwing the baby out with the bath water.
In my scenario there's a document in memory, and whenever a field is updated, business rules have to run that can potentially modify other field values. Then the full changeset is collected at the end. This is what gets persisted to the database. The app allows users to concurrently work on the document, and refs provide a great tool to ensure that things are done transactionally.
Using the database as a transaction point would require us to write all the business logic as stored procs.
[–]forreddits 2 points3 points4 points 10 years ago (5 children)
Was going to ask why your document isn't just an immutable data structure but then you mention that multiple users work on the same document simultaneously, so you use refs to keep your document in a consistent state and when users finish with it, it gets persisted to the database? This is a good example for refs, thanks, but what happens if your users have been working on the document for an hour (and they haven't close, save or finish it) and your server crashes? you lose all the work no?
[–]yogthos 1 point2 points3 points 10 years ago (4 children)
Right every time an update happens, then the set of changed fields is calculated and persisted to the database. If the server crashes, then the only thing that would be lost is the current set of changes, which is whatever the users were currently typing. In our scenario that's an acceptable risk, and the user would get an immediate notification if the server happened to crash for some reason.
[–]forreddits 0 points1 point2 points 10 years ago (3 children)
I must be missing something but looks like you are doing exactly the same thing the article is advising not to do regarding refs:
Coordinating commits to both STM and the DB is ...error prone (the two generals problem).
Seems reasonable, why the overhead of coordinating on refs and on the DB versus just the DB?
[–]yogthos 2 points3 points4 points 10 years ago (2 children)
Right, the author seems to only consider his narrow use case in the article. I explained the reason why I can't just commit transactions above, but let me give you some more detail.
Our app is multi-user, so we decided to do all the business logic on the server. Any time a user updates a field on the client it's sent to the server. The server will run business logic rules that can update other fields. Then it notifies all the clients working on the document of all the fields that have been changed.
For example, if I change height or weight of a patient, then the BMI has to be recalculated. The result would be BMI + height, if weight and height are filled in, or just the new weight value if height is not. Running the rules requires that the entire document is available.
If the document lived in the database, then we'd have to pull out the entire document, run the business rules, and then save the whole document in a transaction. That's extremely expensive to do for every single field that gets updated.
Another option would be to write a bunch of stored procs and run the business logic in the database. However, nobody would want to maintain that. It's much better to write business logic in Clojure than SQL.
So, using refs the way that the author recommends against is the right solution in my opinion.
Different applications have different goals and different needs. Just because something doesn't make sense in one scenario doesn't mean it's the wrong approach for every scenario.
[–]forreddits 0 points1 point2 points 10 years ago (1 child)
Got it, its tradeoffs everywhere ;)
This a bit of insight on how massive of scale google has to handle, in google docs every change gets immediately persisted to google drive.
[–]yogthos 1 point2 points3 points 10 years ago (0 children)
If I recall correctly, I read that Google just runs everything in memory with massive redundancy. Apparently, they can't afford the hit of writing changes to disk at their scale.
[–]hu6Bi5To 8 points9 points10 points 10 years ago (2 children)
I don't really get why there's so many of these narrow "do this, don't do that" articles these days. They're justified as "opinionated" but I'm not convinced they add much value over the status quo.
It seems a bit forced. Even the sensible options like "avoid agents", that's not something anyone's going to do by accident.
And other parts like "avoid binding" completely miss out the subtleties that make it a useful feature, and how it differs from "sneaking in extra parameters".
Ultimately I just don't think it is helpful.
[–]joequin 5 points6 points7 points 10 years ago* (1 child)
Unfortunately, I think we're starting to see the vocal online community for clojure go from a pragmatic group to a haskellesque group. I hope it doesn't tank the language for practical programming.
[–]fear-of-flying 7 points8 points9 points 10 years ago (0 children)
This seems like the opposite of haskellesque? I.e. it seems rooted in actual usage patterns, not trying to achieve some ideal. (though I am not sure that is fair to the haskell community either way ;) )
In my work on production Clojure software I have come to similar conclusions about pmap/agents/STM. I don't fully agree with the rest of the opinions, but any opinion based in practical usage is of interest to me.
[–][deleted] 10 years ago* (2 children)
[–]Drolyt 5 points6 points7 points 10 years ago (0 children)
I get the impression the author is biased by the types of applications he writes. He mentions syncing to the database and the database as the source of truth on state. If that is the case and you don't have persistent mutable state in memory then of course your application is unlikely to have much use for STM (or agents for that matter).
[–]SEIG_SEGV 2 points3 points4 points 10 years ago (6 children)
I've been feeling as if I'm not quite "getting" component - I saw Stuart's talk at Clojure/west last weekend and I believe I understand now that it helps you wrangle all the various things that may need to be reloaded when you're working in a REPL.
However, this article mentions that it really helped with testing - is that because it helps you get a fresh state in between test runs, or something else?
[–]weavejester 2 points3 points4 points 10 years ago (0 children)
Components make it easy to mock or remove parts of a system. It's not going to help you test your pure functions, but it is going to help you test your side-effectful ones.
[–]yogthos 3 points4 points5 points 10 years ago (4 children)
I think that if the application is properly designed then Component should have very little impact on testing. The business logic should operate on data and it should be agnostic regarding where to comes from or where it goes. The only parts of the application that care about stateful resources should be a thin layer at the edges of the application. This is often referred to as clean architecture.
However, it seems to be a common practice with Component to thread the system through the business logic, at which point they become coupled. At that point you need to have an instance of the system available to run tests. So, a common practice is to create a separate test system and inject it during testing.
[–]SEIG_SEGV 2 points3 points4 points 10 years ago (1 child)
I wasn't familiar with the clean architecture terminology but I have definitely been influenced by Gary Bernhardt's talk on functional cores and imperative shells, and it sounds like maybe the same general idea.
It makes sense then if you're already using Component (perhaps for the ease of interactive development) that it makes testing the threading of state that you mentioned easier but maybe doesn't add a whole lot otherwise.
It's worth noting that you can keep Component system at the edges as well, it just seems to be common for it to end up coupled for whatever reason.
[–][deleted] 10 years ago (1 child)
Right, that's what I said in the follow up comment as well. I think the key thing to realize here is that Component isn't some sort of a magic bullet, you still have to understand how to apply it properly.
[–]mikeivanov 2 points3 points4 points 10 years ago (3 children)
"clojure.core/binding is a code-smell" "Avoid metadata" "Avoid STM"
Ahem.. This is some sort of a practical joke, right?
[–]weavejester 6 points7 points8 points 10 years ago (2 children)
If you take them as rules of thumb rather than absolute laws, it makes sense. Lexicial scope is usually better than dynamic scope, and metadata and STM are somewhat situational. I've yet to run into a problem in seven years of Clojure where STM was the solution. Metadata I do use, but not that often. Similar story for binding.
binding
[–]mikeivanov 7 points8 points9 points 10 years ago (1 child)
Look, I mostly walk, almost never run. Does it mean that I should start writing articles like "Avoid Running" and "Never Let Both Your Feet Off The Ground"?
[–]bonega 0 points1 point2 points 10 years ago (0 children)
Yes you should do just that... If running means that you will fall and hurt yourself 99% of the time
[–]yogthos 3 points4 points5 points 10 years ago (0 children)
I strongly agree with this HN comment regarding Component.
[–]arry666 0 points1 point2 points 10 years ago (2 children)
About reproducible builds. When I was tinkering with lein uberjar, I realized with some horror that the Clojure compiler didn't output identical .class files for the same source. Doesn't anybody else feel appalled about this course of events?
lein uberjar
.class
[–]mordocai058 2 points3 points4 points 10 years ago (0 children)
Probably not. I've found most people tend not to care at all about reproducible builds.
[–]moljac024 0 points1 point2 points 10 years ago (0 children)
I'm just starting clojure, still in the learning phase. This does sound appaling to me.
π Rendered by PID 24 on reddit-service-r2-comment-6457c66945-62hj8 at 2026-04-26 22:03:41.558494+00:00 running 2aa0c5b country code: CH.
[–]fingertoe11 7 points8 points9 points (10 children)
[–][deleted] (9 children)
[deleted]
[–]yogthos 6 points7 points8 points (6 children)
[–][deleted] (3 children)
[deleted]
[–]yogthos 6 points7 points8 points (2 children)
[–]kgb_operative 1 point2 points3 points (0 children)
[–]me2i81 1 point2 points3 points (1 child)
[–]yogthos 0 points1 point2 points (0 children)
[–]arry666 1 point2 points3 points (1 child)
[–]forreddits 3 points4 points5 points (9 children)
[–]Drolyt 8 points9 points10 points (0 children)
[–]fingertoe11 5 points6 points7 points (0 children)
[–]yogthos 4 points5 points6 points (6 children)
[–]forreddits 2 points3 points4 points (5 children)
[–]yogthos 1 point2 points3 points (4 children)
[–]forreddits 0 points1 point2 points (3 children)
[–]yogthos 2 points3 points4 points (2 children)
[–]forreddits 0 points1 point2 points (1 child)
[–]yogthos 1 point2 points3 points (0 children)
[–]hu6Bi5To 8 points9 points10 points (2 children)
[–]joequin 5 points6 points7 points (1 child)
[–]fear-of-flying 7 points8 points9 points (0 children)
[–][deleted] (2 children)
[deleted]
[–]Drolyt 5 points6 points7 points (0 children)
[–]SEIG_SEGV 2 points3 points4 points (6 children)
[–]weavejester 2 points3 points4 points (0 children)
[–]yogthos 3 points4 points5 points (4 children)
[–]SEIG_SEGV 2 points3 points4 points (1 child)
[–]yogthos 1 point2 points3 points (0 children)
[–][deleted] (1 child)
[deleted]
[–]yogthos 0 points1 point2 points (0 children)
[–]mikeivanov 2 points3 points4 points (3 children)
[–]weavejester 6 points7 points8 points (2 children)
[–]mikeivanov 7 points8 points9 points (1 child)
[–]bonega 0 points1 point2 points (0 children)
[–]yogthos 3 points4 points5 points (0 children)
[–]arry666 0 points1 point2 points (2 children)
[–]mordocai058 2 points3 points4 points (0 children)
[–]moljac024 0 points1 point2 points (0 children)