Live data from Hacker News

Clojure, the Good Parts

rasterize.io

71–80 of 96 posts

Re: Clojure, the Good Parts

#71
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…

> Absolutely avoid metadata. The worst thing ever is using it like how Reagent does in ClojureScript where it actually provides important program semantics.

Eh? Reagent does not require any metadata, ever. Much less metadata what provides "important program semantics". So I'm pretty puzzled by your comment. Either you have never used Reagent, or our definitions of metadata is really different, which would be odd, given ClojureScript is pretty clear on what metadata is and isn't.

Optionally, as a convenience, Reagent allows "key" to be provided as metadata but that's really a React thing (and available the same way in OM) and that's because it allows React to supply better performance in some cases, but even then you can supply key via means other than metadata if somehow that offends you. If this is somehow "the worst thing ever" I'd suggest you have lived an overly sheltered life :-)

Re: Clojure, the Good Parts

#72
post #15
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…

Haskell noob here. How is STM used in Haskell? What is type-driven STM? In Clojure, I don't recommend it because it's Just Another Place To Stick State. It's cool, but provides little semantic value over compare-and-set! on an atom.

Two Haskell books have chapters on STM:

http://chimera.labs.oreilly.com/books/1230000000929/ch10.htm... http://book.realworldhaskell.org/read/software-transactional...

Re: Clojure, the Good Parts

#73
post #57

Earlier quoted context omitted.

A lot of his points say to offload to services such as a database or queue. It makes sense that if all you are doing in your Clojure application is some simple business logic then you won't need the more sophisticated tools for concurrency and shared state, but if you were trying to write those services in the first place, or if you need higher performance so that sending everything over a socket to a database isn't…

This really only makes sense for service-oriented software. Not all uses of clojure attempt to saturate use of available resources, and here STM is a win. But the OP implicitly assumed everyone was writing "production" software, assumably as part of a commercial service offering.

Although he didn't reiterate it in the STM section, up front he was pretty explicit about what he meant by "production" software, really a specific kind of production software. So the recommendations might not apply if you write a different kind.

To make my biases explicit, I mostly write webapps and data analysis on servers in the cloud. If you use Clojure in significantly different applications, these recommendations might not apply to you.

Re: Clojure, the Good Parts

#74
post #69

Use raw Java concurrency instead. Back to square one.

Um, not really. The main feature that Clojure provides for concurrency is immutability, not just the possibility of using existing data structures in an immutable manner, but an entire suite of immutable data types and data structures. This makes concurrency, even using Java's primitives, like Thread, (which was the original way Clojure was intended to be used anyway,) with Clojure's data structures is a win over usi…

Thanks, skimming through clojure's website it mentions that Clojure simplifies multi-threaded programming in several ways. Because the core data structures are immutable, they can be shared readily between threads. which is exactly what you said, I though its concurrency features where emphasized more on its refs stuff(refs, agents) or futures, delays, promises. Also reading that clojure being hosted is a feature then I guess leveraging the host is idiomatic, (using Thread or other concurrency APIs).

Can you elaborate on why using Thread was the intended way to use Clojure for concurrency?

Re: Clojure, the Good Parts

#76
post #52
post #4

Solid advice (I've been writing Clojure for the last 6 years or so and I agree with pretty much everything). I would like to add, however: * before you decide to use Component, take a look at Mount and see which one suits you better (I settled on mount for both Clojure and ClojureScript and I'm happy so far), * use Timbre: yes. Definitely. In fact, pretty much anything by Peter Taoussanis will be a good choice (for e…

Difficult? I have a few lines in a namespace that grabs `git describe --tags` and a few other things and places them in a json file. This is served up internally by all http-speaking applications as `GET /_internal/build-info`. https://gist.github.com/emidln/8f5993a37ff300e36897debe9c5bf...

Do those lines also name your jars as "project-2.7.11-g03d04c5a.jar" or similar?

Re: Clojure, the Good Parts

#77
post #8

I don't agree on a few points. Global atoms provide a good way to confine state into a single place. In my applications they serve as a in-memory database while everything persistent is written to disk in the form of a log (kafka, file append, you name it). Agents provide a good way to serialise events akin to a transactor. Not every problem requires the parallelism or the concurrency gained by smearing it out into a…

> Global atoms provide a good way to confine state into a single place. I think it's simpler to pass state as an argument to your functions instead. That's less complex and easier to test. > Last but not least, transducers make it onto my list of things to avoid... They are incredibly complex, even brought the spawn of the devil, volatile, into the language. Just for a bit of speedup and core.async integration. Trans…

>> I think it's simpler to pass state as an argument to your functions instead. That's less complex and easier to test.

James,

I was wondering what is the best course of action ini one particular situation. I am using your excellent libraries to create an HTTP API that needs to have state. I usually have an init function and using the ring init feature (see below). How would you not have an atom that hold lets say the DB connection info for a function that renders a html page displaying the version of the database, accessing the dbinfo with @dbinfo (that was updated at the init). Would it be possible to pass in to this function the state? Is it any different if I am calling @dbinfo in the actual function that renders the page or the calling function (router, or app definition)?

:ring {:init myproject.core/init :destroy myproject.core/destroy :handler myproject.core/handler}

Re: Clojure, the Good Parts

#78
post #8

I don't agree on a few points. Global atoms provide a good way to confine state into a single place. In my applications they serve as a in-memory database while everything persistent is written to disk in the form of a log (kafka, file append, you name it). Agents provide a good way to serialise events akin to a transactor. Not every problem requires the parallelism or the concurrency gained by smearing it out into a…

What's so complex about transducers? (let [my-xf (comp (filter even?) (map inc))] (sequence my-xf [1 2 3 4 5])) => (3 5)

Yeah but now try implementing a custom state-full transducer.

Re: Clojure, the Good Parts

#79
post #8

I don't agree on a few points. Global atoms provide a good way to confine state into a single place. In my applications they serve as a in-memory database while everything persistent is written to disk in the form of a log (kafka, file append, you name it). Agents provide a good way to serialise events akin to a transactor. Not every problem requires the parallelism or the concurrency gained by smearing it out into a…

> Global atoms provide a good way to confine state into a single place. I think it's simpler to pass state as an argument to your functions instead. That's less complex and easier to test. > Last but not least, transducers make it onto my list of things to avoid... They are incredibly complex, even brought the spawn of the devil, volatile, into the language. Just for a bit of speedup and core.async integration. Trans…

> I think it's simpler to pass state as an argument to your functions instead. That's less complex and easier to test.

I completely agree with that sentiment. But I prefer to execute those functions with swap! on my application state.

That way I can always inspect it in the repl during development and production. Which is not so easy when it's just bound in the local variable of some thread somewhere.

As for transducers, tbh I haven't encountered the use case you describe yet.

Re: Clojure, the Good Parts

#80
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…

> Absolutely avoid metadata. The worst thing ever is using it like how Reagent does in ClojureScript where it actually provides important program semantics. Eh? Reagent does not require any metadata, ever. Much less metadata what provides "important program semantics". So I'm pretty puzzled by your comment. Either you have never used Reagent, or our definitions of metadata is really different, which would be odd, giv…

> Eh? Reagent does not require any metadata, ever.

I am no expert in reagent, but I think it requires it to access Reacts component lifecycle callbacks like `component-did-mount` and such.

Post reply on HN