Live data from Hacker News

Clojure, the Good Parts

rasterize.io

41–50 of 96 posts

Re: Clojure, the Good Parts

#41
post #38

Earlier quoted context omitted.

The drawback here is that the STM (at least the Clojure implementation few years ago when I tested it) is orders of magnitude slower than simple atomic reference . It actually does not have to be, but this is how it is (was) implemented. I built a simple STM (in Java) as part of my bachelor thesis and its performance was comparable to the atomic reference.

If all you need is a simple atomic reference, then great. I'm not convinced a single atomic reference sufficiently covers enough use cases, however.

Yes, it probably does not, and I think that using STM is actually fine in Clojure. Just you have to pay attention to the limitations.

Re: Clojure, the Good Parts

#42
I agree that using binding to avoid passing arguments is a bad design. That is not the only use of binding or more generally dynamic/special vars.

Clojure has naive implementations of pmap, send, send-off & future. They're useful in the REPL, but you need to understand their shortcomings before using in would-be production code. Promise & delay have limitations, but are not so hamstrung as former functions.

Even if you don't expect any function to preserve meta, metadata is still useful. E.g., I've used it on a compiler to provide compiler tracing and decompilation.

Component is not essential. It helps if you're accustomed to OO languages. It's arguably better than the procedural style of with-redefs & bindings.

As amazing as core.async is, I am not a fan. I'd rather use queues, logs or an actor library.

Re: Clojure, the Good Parts

#44
post #10

It's sad to see that STM is not recommended. It is hugely important in Haskell. I jump to believe that this is an artifact of type-driven STM, but it may be something else instead. I've recently moved from Component to Mount. It is less powerful but just a vast syntactic overhead reduction. Absolutely avoid metadata. The worst thing ever is using it like how Reagent does in ClojureScript where it actually provides im…

It's sad to see that STM is not recommended. Actually, this is not recommendation for a specific use case - a (web based) database application. For applications that require to manage state internally it might be still way to go (sorry, I am not a Clojure user).

That's true and a good point! I'm reading into this as talking to a much broader context.

STM in a simple request->response web application probably is overkill and I'm much more aligned with his recommendation now.

Re: Clojure, the Good Parts

#46

Earlier quoted context omitted.

So what would you recommend that function look like? I think it is bad taste to say (with-read-txn db-name (put! db-name)) - no reason you should specify again what db you are dealing with.

There's plenty of reason: you can put any code you like inside of `with-read-txn`, including closures that are evaluated lazily. If you dislike the duplication, create a syntactic form that allows less, like this: (transaction-> db-name (put! ...) ...) This doesn't lend itself to every kind of action, but it is narrower. Alternately, create a variadic version of `put!` which guarantees eager evaluation inside of a tr…

Ok I see your point. I am curious how that would happen though - essentially you'll need to bind the txn to a different transaction from the one intended and the whole thing locks up.

I am curious how to guarantee eager evaluation - dorun, doall and run! are all sequence-oriented right?

Re: Clojure, the Good Parts

#47
post #3

Pretty good list that I mostly agree with. I think the only point of contention I may have is with using timbre--having tried it in the past, I found it didn't do much that clojure.tools.logging couldn't do for most use-cases, and added configuration complexity while not sparing me the trouble of dealing with logback XML configs and whatnot--Java logging seems to rears its ugly head no matter what you do, especially…

Author here. I agree, Timbre is new, and has some rough edges, but in my projects, I've found them worth putting up with. In my current project (18k LoClojure), I think the only serious dependency I have that uses j.u.logging or SLF4J is Datomic. Timbre has an interop library that will pipe java logs through timbre. I agree knowledge of how Java logging works is still useful, but I'm not willing to be part of the pro…

Can you ELIAJPWKVLAC* why Timbre is so much better than, say, Logback? I imagine not having to write XML configuration is one thing, but what else?

* Explain Like I'm A Java Programmer Who Knows Very Little About Clojure

Re: Clojure, the Good Parts

#49

Programmers should know their trade-offs. It's not so much that STM should be avoided, but that the use cases it was designed for don't often present themselves in production. Same with agents, core.async, metadata, etc. So I also get a bit twitchy when I hear for wholesale use of Timbre, Component, Schema. Every one of these libraries has tradeoffs. And those tradeoffs should be understood before adopting them. As a…

Perhaps "understand all the trade-offs" should be the mantra of programming, in any language.

Yes, yes, a thousand times yes! (Perhaps too close to James Joyce, but that's not the point.) Understanding cost/benefit and making good decisions is the basis of winning a lot of games, the game of programming included! A programming shop needs to be good at the task of optimizing its programming, obviously, and as in any optimization task, cost/benefit comes into play.

Re: Clojure, the Good Parts

#50
Most of these are excellent pieces of advice, and practices I generally try to adhere to. I don't use schema as much as I used to, but timbre is fantastic, clojure.test is great, and all of the core points are excellent. I've never had cause to use agents or STM, and atoms are best used when enclosing some stateful function.

core.async is also great, but not without caveats, and it also has some strong footgun potential. I've written a little bit on the subject http://blog.goose.haus/2016/04/01/the-puts-and-takes-of-core... and http://blog.goose.haus/2016/04/04/producers-and-error-handli..., with more coming, but the tl;dr is that core.async will swallow exceptions by default and there are a few other gotchas.

Post reply on HN