Fork me on GitHub
Lucas Barbosa17:09:48

Is there any comprehensible guide to emacs + clojure recommended for a beginner?

Lucas Barbosa17:09:07

I have a tiny experience with clojure and absolutely 0 knowledge about emacs


@lvbarbosa absolutely! If you're an emacs beginner (and especially if you have any vim experience), I recommend using Spacemacs instead of vanilla Emacs. If you decide to go that route, check out: or If you decide to go with regular emacs, try or


Those are all reasonably up-to-date IIRC. There are also friendly #emacs and #spacemacs channels here on Clojurians, and a terrific #beginners channel for asking Clojure questions.

Lucas Barbosa18:09:10

@eggsyntax if I would like to go with regular emacs, is there any difference between using it on my osx bash vs using the gui version?

Lucas Barbosa18:09:49

I mean, of course there is the point where bash is bash and GUI is GUi

Lucas Barbosa18:09:06

but I always thought of emacs as being a terminal editor


Hmm, good question. I'm not sure -- I use spacemacs, which essentially always acts as a gui version (you can get it to be inside the terminal but it's a bit awkward). Because emacs startup takes a second or two, emacsers tend do do long-running emacs sessions, so it kind of makes sense to use a version separate from any particular terminal -- not like vim, where you start & quit instances at the drop of a hat. But either way works really well, it's just a matter of preference.


ie if you need to do some little thing, vimmers tend to start a new instance; emacsers tend to do it in a buffer in their already-running instance. I generally keep my emacs instance running all the time, and I think a lot of folks do the same.

Lucas Barbosa18:09:06

I will try out standard emacs on the gui

Lucas Barbosa18:09:29

learn the basics and then start doing some clojure on it

Lucas Barbosa18:09:40

I’ll definitely try spacemacs later


@lvbarbosa spacemacs is actually easier (IMHO) for beginners. I encourage you to either use spacemacs or some batteries-included emacs distribution, unless you really want to learn it from the ground up. But some batteries-included version will give you a much easier learning curve, and it can be pretty tough trying to learn emacs/vim at the same time as a new language (especially if you haven't done much with lisp or with other functional langs). But your call, of course! 🙂

Lucas Barbosa18:09:16

@eggsyntax I see… I already have a little bit of experience using Clojure, have been studying and practice for the past few months


Oh, gotcha, so it's not both of them from scratch at the same moment 🙂

Lucas Barbosa18:09:06

Yes.. but I am kind of afraid of emacs 👀

Lucas Barbosa18:09:25

That’s why I will dedicate some time to it

Lucas Barbosa18:09:36

I have literally no idea on how it works


Do you have vim experience?


(if so, you'll probably want evil-mode, so you can leverage the key bindings you already know)

Lucas Barbosa18:09:52

Just a little bit, enough for editing files over ssh when needed. Like entering insert mode, exiting insert mode and writing my changes


Default emacs has a pretty good interactive tutorial, though I would also point out that you can get a passable REPL development environment in lots of different editors these days

Lucas Barbosa18:09:00

@chris_johnson I’ve tried Atom’s proto-repl, but there’s something in Atom that doesn’t make me feel good


Atom, IntelliJ IDEA, possibly VS Code (though I haven't gone back to look recently and this was behind Atom last I checked)

Lucas Barbosa18:09:21

I don’t know, there’s an input delay, compared to sublime, for instance

Lucas Barbosa18:09:35

this is basically what I am looking for in Emacs, I want a fast experience


I mean, I'm conversant with all of those editors and I make the conscious choice to use Emacs + CIDER because it is, for me, a whole other class of experience


But if you're worried about the two streams of self-education at once making each one slower, it is entirely possible to learn one first and then the other, that's all I'm saying.


I think learning Clojure and learning Emacs are both very worthwhile endeavors that will give you a really useful perspective even on other languages and editors, and I definitely encourage you to dive in and start having The Best Experience from the get-go


But if it's a choice between An Okay Experience with VS Code and bouncing off the whole project, I would encourage you to go for An Okay Experience. 😄

Lucas Barbosa18:09:50

Well, I am learning just for fun

Lucas Barbosa18:09:07

not any professional requirement or project


That’s the best kind of learning!

Lucas Barbosa18:09:47

Indeed, what I work with has almost nothing to do with programming. Well, I use a declarative programming language to do knowledge engineering, but it isn’t even close to “real” development


So, another thing in addition to the excellent recommendation to grab some kind of batteries-included setup for Emacs is that Emacs itself has a fairly decent built-in tutorial for the basic stuff like moving around in a file, opening files, the sort of conceptual model of how Emacs thinks about things


i'm another new to Emacs and Clojure - don't want to be overwhelmed, so i'm just using vanilla Emacs for now - then i'll start adding clojure-mode and CIDER once i know more


already got bitten by using Brave Clojure's setup

Lucas Barbosa18:09:14

But yeah, learning Clojure has been a very nice time


You get to it by launching Emacs and hitting C-h t (`<Control>` and h together, followed by t by itself)

Lucas Barbosa19:09:38

Great, I will try that out soon

Lucas Barbosa19:09:58

thank you guys for the tips, really appreciate them! @eggsyntax @chris_johnson


Anytime 🙂


Seconding @chris_johnson that emacs + cider + clojure really is worlds beyond anything else, it's pretty much a match made in heaven (although Cursive/IntelliJ is awesome; it's just impossible to beat that combo 🙂 ). So yeah, it's a learning curve, but it's got a hell of a payoff...


I could use some help trying to make a bit of code more concise. Right now I have a definition that looks like this:

(def rook
  [{:fn (fn [[x y]] [(inc x) y]) :max nil}
   {:fn (fn [[x y]] [(dec x) y]) :max nil}
   {:fn (fn [[x y]] [x (inc y)]) :max nil}
   {:fn (fn [[x y]] [x (dec y)]) :max nil}])
I don't want to have to repeat so much there, and I'm trying to figure out how to get that same result through a simpler definition, like this (as an example):
{:functions [[(inc x) y] [(dec x) y] [x (inc y)] [x (dec y)]] :max nil}
Hopefully that makes sense. Basically I don't love how I have to repeat so much in that first definition, but I don't understand how to make it more concise. Is there some way to not have to do the anonymous function definition over and over? Any help pointing me in the right direction would be appreciated.


boot.user=> (defn define-piece [{:keys [x-fn y-fn max] :or {x-fn identity, y-fn identity}}]
       #_=>   {:fn (fn [[x y]] [(x-fn x) (y-fn y)]) :max max})
boot.user=> ((:fn (define-piece {:x-fn inc})) [1 2])
[2 2]
something like this?


This works perfectly, thanks!


no problem 🙂


feel free to change the name


…jumping in late on the emacs thread so I’ll simply add: keep it simple, especially at first. There is so much functionality you can get buried and feel like you’re never going to get a handle on things. And especially if you use a curated & pre-packaged distro, because those tend to heap in functionality to cover the wants and needs of diverse followers. I would suggest you can get pretty far with basic navigation, editing, search/replace, and interacting in the repl. Get going with that, and when you need another feature (e.g. interactive debugging, refactoring, magit, …) it will be easier to learn just that one new thing.


thank you for confirming my plan 🙂


How come I can't use + in the name of a binding in a let? I can use most other symbols, I'm confused why + causes an error


boot.user=> (let [a+y 3] a+y)
seems to work for me


Ahh, I suppose it is specifically + and a number then.

(let [1+2 3] 1+2)


I thought you couldn't start the name of a binding with a number


(let [+2 3] +2) also doesn't work, while (let [=2 3] =2) does, so there's something happening with + and numbers


A single + or - followed by only digits is parsed as a number


Scratch that, a single + or - followed by a digit is parsed as a number. +2w isn't a valid symbol either, because clojure (and clojurescript) tries and fails to parse it as a number. So, yeah, avoid doing that in a symbol. And it doesn't matter where it is, in a let or a def or wherever, it is parsed as a number. I don't know if this is documented anywhere, it probably should be.


Hey I am trying to use docker together with Clojure and I’m wondering if anyone has any tips on a workflow for doing so. I was able to setup a container with Clojure + Java + Boot and I can launch a REPL just fine, but if I try to connect to it from the host machine things start to break down


I launched the Boot REPL with a specific port and made sure to expose that same port to the host machine using Docker but it still seems like I am doing something wrong


Hi @adamkowalski and welcome! I think that it would make it easier for us to help if we had a better picture of what you mean precisely by “things start to break down” and “seems like I am doing something wrong” - do you mean that the REPL never connects to the port, or that you get connected but the REPL behavior is not the same as running on the host machine directly, or something else?


Ah sorry about that I should have gave you more context, let me fire everything up again and I’ll give you the exact error messages i’m getting


but it seems like its able to establish a connection and then immediately disconnects


Ok so I launch my clojure container exposing port 3000


Then I run boot repl -p 3000


I open emacs and run cider connect choosing localhost as the host and port 3000


[nREPL] Establishing direct connection to localhost:3000 ... [nREPL] Direct connection to localhost:3000 established [nREPL] Connection closed unexpectedly (connection broken by remote peer) nrepl-send-sync-request: Sync nREPL request timed out (op clone id 1)


I was thinking that maybe I need to change the host from localhost to the ip address of the docker container, but after checking their docs it seems like exposing a port should allow me to access it using localhost on my host machine


how are you invoking the container @adamkowalski?


docker run --rm -it -p 3000:3000 clojure


where clojure is a container I built that sits on top of the open-jdk8 alpine container


I think there is an issue with alpine that people have run into


I think the root cause is that alpine doesn't do ipv6, but nREPL requests binding on a ipv6 IP port 3000 by default


Thanks for the tip maybe I should try something else. Is that because they don’t use glibc and use musl-libc instead?


oh the ipv6 thing


yeah it's ipv6 related.


Do you have another os that you can recommend that is pretty slim and still works well for this kindof setup?


you can probably get around it by specifying boot repl -p 3000 -b


or is it best to just bite the bullet and start using ubuntu and just pay for the extra size


alpine is fine


You are a genius my friend


I added the -b and it all works


I guess isn’t going to work for external ip’s or something or why would that be an issue


by default nREPL is binding on ::0 (ipv6)


and it needs to be ::1?


no -- it needs to be for ipv4


alright fair enough. and do you usually just launch boot like that every time or do you just add the configuration options to your build.boot file?


dunno, not a boot expert.


Alright well thanks for the help 🙂 I’ll be able to take it from here I hope!


I use a bare socket REPL for my dev


oh interesting


is there a reason why?


and I use inf-clojure instead of cider


I don't like nREPL for various reasons, and don't care about autocomplete.


and other niceties that it provides. it also is a bit laggy. Rich has written a bit deeper about nREPL vs plain REPLs on the mailing list, worth a peek.


Better than my hot take


Alright i’ll try to find that and read up on it. I’ve mainly just been using boot because it seems like it gives you a really nice composable build pipeline


I used lein in the past, and when I was doing frontend work I used something like figwheel. But if you use one of the lein plugins it seems like they take over your project and its hard to mix orthogonal plugins


there will be an official dependency fetcher and clojure launcher soon


both lein and boot are nice for all the other extras that aren't just fetching deps and launching a JVM


the official launcher will hit package managers soon -- it's already available on homebrew, and linux flavors coming Real Soon


The official launcher starts very quickly.


between 0.4-1.1s on a modern machine - which is great compared to what we're used to


I can't believe no one filed the nREPL bug!


Oh yeah thats night and day haha, maybe it might be reasonable to use clojure for scripts in the future then


But I think its good there is going to be some standardization on how we launch and fetch dependencies. Whenever I try to introduce new people to Clojure that is always one of the hardest part to get them to wrap their minds around.