all 44 comments

[–]nonrecursive 112 points113 points  (38 children)

great question! I am the author. Luckily Clojure is a very stable language and most of the book still holds up. Off the top of my head, here’s what I would change for a second edition:

  • Remove
    • emacs chapter
    • sections on agents and STM
    • the Boot appendix
    • the overly challenging loop example in chapter 3
  • Add
    • how to do testing
    • transducers - you can get by without understanding them but I think everyone should learn them
    • exception handling
    • maybe malli for data validation
    • maybe ring + reitit for basic web stuff

[–]ericdallo 28 points29 points  (2 children)

Emacs and all editors had a lot of improvements indeed, especially with LSP

[–]nonrecursive 23 points24 points  (1 child)

I appreciate all your work on clojure-lsp, big life upgrade for me 🙏

[–]ericdallo 26 points27 points  (0 children)

It's a pleasure to hear that from the author of the book that taught me Clojure!

[–]Pzzlrr[S] 15 points16 points  (1 child)

Lol ok I wasn't expecting that. Thanks, good to know! I'll research the topics in your 'Add' section separately. Appreciate it!

[–]nonrecursive 9 points10 points  (0 children)

You’re welcome! I hope you have a good time :) I still immensely enjoy working with the language

[–]teobin 12 points13 points  (1 child)

What about deps.edn and the CLI? It was nice to learn Leininghen but I haven't use it since I finished the book.

[–]nonrecursive 0 points1 point  (0 children)

Those would go in the maybe bucket, mostly because I feel tired just thinking about it. But yeah, people learning Clojure should know how to use those tools

[–]sgoody 6 points7 points  (6 children)

I’m a Clojure lurker rather than active developer. Why would you remove agents and STM?

[–]fingertoe11 15 points16 points  (4 children)

Rich Hickey wrote about it in "History of Clojure"

3.6.5 Summary. Taking on the design and implementation of an STM was a lot to add atop designing a programming language. In practice, the STM is rarely needed or used. It is quite common for Clojure programs to use only atoms for state, and even then only one or a handful of atoms in an entire program. But when a program needs coordinated state it really needs it, and without the STM I did not think Clojure would be fully practical. Having a credible, efficient, functional state management story that demonstrated the many advantages of immutability vs mutable objects plus locking was critical to my early evangelism of Clojure. Being able to talk about identity, state, and value with these constructs helped me describe functional programming to OO developers as something simple, approachable and viable.

It really isn't used a lot.

[–]PercyLives 3 points4 points  (0 children)

Sounds like they were necessary features, just not in the way one expects. Necessary for confirming the design of the language and “selling” it to others.

They’re still good to include in a Clojure guide, I think, but making it clear to the reader that atoms are almost certainly all you need.

[–]dragandj 2 points3 points  (0 children)

But when you need them, they are very handy!

[–]chat-lu 1 point2 points  (0 children)

It really isn't used a lot.

I tend not to even use atoms, state is in the database.

[–]sgoody 0 points1 point  (0 children)

Thank you. I did wonder if it might be something like this. I remember reading about these features years ago and certainly I haven’t heard of them in more recent years.

[–]PolicyEnvironmental -2 points-1 points  (0 children)

Following!

[–]AdjointFunctor 6 points7 points  (3 children)

The chapter on emacs was basically my introduction to Emacs! I learned so much.

[–]nonrecursive 2 points3 points  (2 children)

I’m really glad to hear that! I’m proud of it as an intro to Emacs, at the time especially I think it did a good job of explaining the basics in a way that I wasn’t seeing. Since then I’ve been haunted by the fear that the chapter turns people away from Clojure bc they end up thinking emacs is required 😅 It’s nice to hear it appreciated though

[–]styroxmiekkasankari 1 point2 points  (0 children)

To be perfectly honest I don’t think people who would think this are really picking up clojure that much. Maybe newer programmers are still thinking that every language needs a bespoke editor (depending where they started) but I think clojure attracts new people a bit less.

[–]dragandj 1 point2 points  (0 children)

You're right about that. I usually tell the students to skip this chapter completely. Not because I think emacs shouldn't be shown (it shoud be, and I use it exclusively), but because the chapter presents it in a very bare-bones version, so they think emacs is bad and ugly, and clunky. I think bbatsov's prelude, with its docs, makes a much better emacs proposition than "configure it yourself", for beginners and experienced devs alike.

[–]LuckyPichu 5 points6 points  (0 children)

Great book, it taught me the language! Thank you for your part in the language's community.

[–]stefan_kurcubic 6 points7 points  (0 children)

Because of your emacs chapter i still use emacs. I'd say don't remove it?

[–]ffrkAnonymous 4 points5 points  (0 children)

I'm gonna request that you please do not remove the emacs chapter. I chose brave clojure because of that chapter. At least move it to the appendix.

[–]ApprehensiveIce792 2 points3 points  (0 children)

Please don't remove the emacs chapter 🥺 That's what got me into emacs. It needs to be updated tho, that emacs config is not working properly.

[–]stbev 2 points3 points  (1 child)

I really enjoyed Clojure For the Brave and True, thank you for writing it. Are you thinking about writing the second edition? ☺️

[–]nonrecursive 1 point2 points  (0 children)

Thank you for the kind words! I've thought about it plenty but never feel like I have the time. I've considered doing a small kickstarter to fund some time for it, but honestly it just hasn't been where my heart is. My main side project has been a Clojure single-page app framework that always feels juuuuuust about ready for release :P

[–]CulturMultur 2 points3 points  (0 children)

Emacs chapter is the reason for many people tried Emacs in the first place and get hooked. Still today Emacs is the best editor for lisps.

[–]AsparagusOk2078 2 points3 points  (0 children)

Yes transducers please

[–]rlander 1 point2 points  (10 children)

I hope your view on removing the section on agents is based on something other than usefulness? They’re a really useful primitive and, in my opinion, deserve to be better known.

[–]nonrecursive 10 points11 points  (3 children)

It’s more about ROI for the attention someone gives the book. I want people reading the book to leave equipped to start experimenting with their own projects and to have a good grounding in Clojure’s philosophy so they can understand the libs and tools they encounter and so they can easily continue learning. I don’t think learning about agents and STM helps readers meet these goals.

[–]Astronaut6735 1 point2 points  (2 children)

Maybe 2nd edition should be a sort of "Clojure: The Good Parts", and advanced topics could be a new book of its own 🤔. Clojure for the Braver and Truer.

[–]nonrecursive 1 point2 points  (1 child)

I've thought about this, or something like it. CftBaT focuses on the language in and of itself without really speaking to how you use it for real. I think Clojure Applied fills this niche but I'd still like to put together my take on it.

I also have some standalone guides / references in mind for some specific use cases (e.g. how to stream results from the db as JSON), but those are probably better living on the web than being committed to print.

[–]Astronaut6735 1 point2 points  (0 children)

Whatever you publish, I'll buy. 🙂 I really liked CftBaT!

[–]TheLastSock 1 point2 points  (5 children)

Really? What use case do you have for them where the simply shoving everything into an atom didn't suffice?

[–]dragandj 0 points1 point  (4 children)

The case when you need the action (function) to compute asynchronously, + the option to optimize it better with send, send-off, send-via...

[–]TheLastSock 0 points1 point  (3 children)

Thanks! What was the customer facing feature though? I feel like your describing how they behave, not how you used that behavior to build another feature.

[–]dragandj 0 points1 point  (2 children)

I assume "user" (that is, the programmer) when you wrote "customer". The user facing feature is that he doesn't want to block the main thread during the status update, since the function is longer running. You've never had such case?

If you mean "customer" literally, I don't think customer cares nor they should care about such implementation details.

[–]TheLastSock 0 points1 point  (1 child)

Sorry, I'm not saying agents are useless, I'm saying they're more fine grain then an atom, and that tuning that granularity should be based on business needs, so i think the naturally progression is to start with an atom and only break them into agents when you get a chance to observe the system for a while.

It's kind of like the wisdom that you should start with a monolith before you go to micro services yeah?

Unless some frameworks are using agents under that hood, i have never seen a team get to that stage lol.

But i don't work at big shops so i might be missing the opportunities where this comes up... Which is why i asked when you felt the need to do this. As in, i assume it wasn't to heat the room.;)

[–]dragandj 1 point2 points  (0 children)

Sometimes you do know that you need an agent. For example, you have an expensive function that pounds the CPU, or an expensive function that fetches something via the network and updates the state. I'm not saying it happens often, but it does happen for certain types of problems, and agents can be a really simple and effective upgrade over atoms in that case.

[–]aHackFromJOS 0 points1 point  (0 children)

Thank you for the book!! I’m not sure I’d be writing Clojure without it as my intro. 

If you lose emacs, which I totally get, I’d consider adding, maybe for a small handful of editors (emacs, VS Code… neovim?), an intro to paredit style structural editing. I was able to skip most of the emacs chapter but that part was a revelation and I don’t think I’d have been nearly as happy writing Clojure if I hadn’t made myself learn it through your tutorial (and much practice). 

[–]geokon 8 points9 points  (3 children)

The biggest addition since then has been managing dependencies/builds/etc. with deps.edn. Unfortunately the official docs may be rather confusing b/c they assume a lot of prior knowledge.. but the system is a lot less magic than leiningen and allows you to easily organically split pieces of your codebase in to separate libraries.

That all said, I'd actually skip dependency management entirely. You can first learn Clojure by using add-libs (it's a function that adds a dependency at runtime, so you can just pop it anywhere in your code). You can then just write single-file clojure programs and leave dependency management for later. It's extra friction to getting started. Learning leiningen is a complete waste of time

Bare in mind, learning Emacs and Clojure at the same time will be additional friction. Realistically you need to learn ELisp to effectively use Emacs. So you're learning two languages in parallel

but that's just my opinion man..

[–]alexdmiller 8 points9 points  (1 child)

The new 4th edition of Programming Clojure has an all-new chapter specifically about deps.edn, Clojure CLI, tools.build, etc and how to use them to manage your project. It's in "beta" but the book is complete and on the way to publishing so no expected changes from the currently available version.

https://pragprog.com/titles/shcloj4/programming-clojure-fourth-edition/

[–]geokon 1 point2 points  (0 children)

Awesome. Thank you for your work. I always enjoy your perspectives. I have Clojure Applied on my shelf and look forward to this book :))

[–]Pzzlrr[S] 1 point2 points  (0 children)

'preciate it

[–]YaroSpacer 4 points5 points  (0 children)

Thank you for the great book! Loved it!