Fork me on GitHub
Ben Sless08:01:28

Anyone has the reverse threading macro at hand?


I don't recall ever hearing of the reverse threading macro. how does it behave differently than threading macros built into Clojure?

Alex Miller (Clojure team)14:01:56

it's like, the opposite, man

😂 13

(defmacro <-
  (loop [form form, out '[]]
    (if (seq? form)
      (let [f (first form)
            args (first (rest form))]
        (recur args (conj out f)))
      (list* '-> (reverse (conj out form))))))

(macroexpand-1 '(<- (inc (inc 1)))) ;;=> (-> 1 inc inc)


(I'm sure I can nerd snipe you into better versions of this)


So, here is the code that doesn't need a Clojure threading macro, please give me the same but using a Clojure threading macro? I guess that is one way to reverse it 🙂


@andy.fingerhut That was my interpretation of reverse threading macro asked by bsless


Now if you can just make it so that you invoke it like this: ((inc (inc 1)) <-) 🙂


(inc inc 1 <-)


maybe something for 1.11, will require some new evaluation rules...

Ben Sless16:01:24

Yes! that's the one, thank you 🙂


fwiw in real code I call it else->>

🙂 1

really awesome macro

🙏 3
☝️ 3

I keep staring at this and can’t quite wrap my head around it. How does threading the forms in reverse order not result in the forms getting executed in reverse order?


With this macro you thread other macros (if let when etc) for which evaluation order is not the applicative order. Try to expand a simple example with pen & paper.


I’ve worked out the example a bit more so it works in the repl when you paste it

(def fn-which-may-return-falsey identity)
 (def fn-which-may-return-nil identity)
 (def a 2)
 (def y 4)
   (if (odd? a) 1)
   (let [a (quot a 2)])
   (when-let [x (fn-which-may-return-falsey a)])
   (when-some [b (fn-which-may-return-nil x)])
   #_(when (seq x)) ;;; type incompatible
   (do (println x))
   (if (odd? (+ x y)) 2)
 (macroexpand '(<<-
   (if (odd? a) 1)
   (let [a (quot a 2)])
   (when-let [x (fn-which-may-return-falsey a)])
   (when-some [b (fn-which-may-return-nil x)])
   ; (when (seq x))
   (do (println x))
   (if (odd? (+ x y)) 2)

Daniel Jomphe14:12:48

Hi! I'm experimenting with Christophe's macro to see if it's usable with our project and dev setup. clj-kondo raises warnings in many situations. I started playing with its config and I wonder... Have you found a robust way to make clj-kondo happy with idiomatic usage of the macro?

Daniel Jomphe14:12:08

The following might help just a bit:


@U0514DPR7 writing a hook is your best bet with a macro like this


clj-kondo can run clojure macros now too, you just have to place them in your .clj-kondo folder and hook them up in the config

Daniel Jomphe14:12:49

But I both don't fully understand what will happen for clj-kondo by doing this • is it sane to as it to treat <<- aka else->> as ->> ? • as for the example if I'm not even sure if the warning raised by clk-kondo should be a real warning even in Christophe's and Mark's examples.

Daniel Jomphe14:12:46

Thanks a lot Michiel; not sure if I'll be able to run with this but at least I know that we know that a solution lies ahead if we really want it! 🙂


Just copy the macro to :

and then configure as {:hooks {:macroexpand {cond-better/else cond-better/else}}}


make sure cond_better.clj looks like:

(ns cond-better)
(defmacro else ...)

Daniel Jomphe14:12:08

ok, the scroll position of your link in my screen showed me things about rewrite-clj nodes, but the actual macroexpand doc you linked too (and your help above) make it much more friendly to try, thanks again, I'll report back


yeah I don't know what's up with linking to relative uris (or how do you call these), it often fails for me too

Daniel Jomphe14:12:37

Oh a few days ago I stepped upon this new Chrome deep-linking-highlighting feature, let's see how slack renders it and how following the link shows the page,clojure.set/union%20,clojure.set/union%20...)

Daniel Jomphe14:12:32

Wow, this looks like it's magical! Kondo still reports some cases of missing else branches, but it looks like it only happens in the one-liners and those don't make sense. The example with more lines is more realistic and Kondo seems to have picked up the threading of the else branch of the if. 🙂

🎉 1
Daniel Jomphe14:12:45

Michiel, this is very impressive... Clojure seems to give us so often tooling that works well at every layer!

🎉 1
clojure-spin 1

That thread has example usage too


Some general thoughts about beginner friendliness, adoption and learnability of Clojure. Disclaimer: I’m teaching web programming/development for designers part-time, so I’m strongly biased. IMHO web programming (frontend) is likely one of the best introductions to programming for several reasons: * Very fast feedback loops: You code, save and you see the results immediatly. * GUI/user centric: printing stuff on your terminal/REPL ist not very exciting for most beginners. * Familiar: you build something you already understand as a user and conceptually, very few concepts have to be learned. * Practical / reach: you can publish a website easily, you create something that you can show and has value. * Creative: the web is an open system with tons of capabilities, from drawing to calculating to communicating etc. However, most introductions to Clojure seem to start with JVM Clojure and almost none of them are truly introductory. Java and the JVM are scary! Someone who is familiar with these and has substantial experience will consider Clojure, because it solves problems they know from experience. Others are likely comming from learning Scheme/Racket via SICP etc. (Scheme has a strong tradition as a educational language and fantastic books/resources) and they are looking for a Lisp that has a strong pragmatic focus. They will happily take those hurdles. But what about real beginners. They might have written “Hello World!” with Python and know what a loop is or created a rudimentary HTML/CSS website. Or maybe they don’t even know where to start. I think there might be an opportunity to build learning resouces for real beginners based on the web and ClojureScript. Likely a subset of ClojureScript, with a set libaries focussed on learning, or even a simpler learning DSL that is built on top of ClojureScript. Examples of thinkable libraries/features: * easy and fast setup. There needs to be some time limit, like 5 minutes. * a simple, constrained GUI library * a networking library based on AJAX or websockets * maybe canvas/webgl to create some simple games All of these features have to be stripped down to the essence, have very strong “just works” conventions and very little to no configurability. Sorry for the long rant. But I really wonder what you guys think of these ideas, especially since I don’t know all the beginner resources for Clojure. Even pointers like X does already do that or have a look at Y are welcome.


My view (which I have previously expressed in the Clojure Slack) is that I don’t see Clojure as a suitable language to teach to beginners. Similarly, I don’t see Java/Kotlin/C++ as suitable languages either. when learning to program as a beginner, you need to limit the surface area of things that you need to learn and the above languages don’t do that sufficiently for my liking.

✔️ 4

When I learned Clojure, I already knew Java and I had already learned Emacs and Slime (it was a while ago). I personally would have struggled if hadn’t.


(I’m still interested in hearing about tools/resources that you can learn in five minutes and hearing about experiences of beginners leaning Clojure because I could be completely wrong, of course.)


Those are very good points. I agree especially with the surface area part. A beginner should be programming against very simple interfaces at the start. I think a Lisp is inherently suitable, because of its meta programming capabilities and dynamism. You can build a library of macros around a beginner experience. I disagree with having to learn Emacs though. I think VSCode and others enable a better beginner experience.


If they are real beginners, then would such a course include learning HTML, CSS, AJAX, too? Or assume you learned those already somewhere else?


No! I thought more of having very constrained abstractions that use those things under the hood, and maybe you can dig down gradually to expose them over time.

👍 3

I believe it was lighttable or something like that which seemingly had the “batteries super included” approach to things with built in templates and such.


But I believe it was also abandoned a few years ago.

👍 3

ClojureBridge was designed to teach Clojure to total beginners (although many attendees were already programmers in other languages) and one of the struggles we faced was trying to figure out learning exercises that were fun and provided the sort of feedback students like best. I think ClojureBridge has tried several curricula with at least one focused on graphics (Quil on the JVM, I think).

👍 3

Ah, there are five choices of app now, including one web app...


Turtles all the way down


@hobosarefriends Yeah, LightTable was really good in the early days but once it became incompatible with macOS after one of the O/S releases, it wasn't a good experience for teaching. I think ClojureBridge used NightCode for a while which is a really simple Clojure all-in-one editor. [Confirmed: see ]


None of that I heard about while learning


I’m really thinking in terms of “Introduction to Programming” and not “Introduction to Clojure”


There are many people who would benefit from learning how to program, not necessarily to become programmers full-time. I’m being a bit “in your face” here: There are things you cant put in front of 70% of beginners at the frist hour or so. * data structure concepts * lots of declarations * not seing a GUI * lots of setup Essentially they have to see some satisfying results in a couple of minutes.


I think this part of clojure has been improving dramatically. For minimizing setup, I think could be a really good fit. You could even have a download that included all the dependencies you were interested in. When it comes to GUIs, I'm pretty biased since that's the project I've been working, The hello world for membrane is:

(require '[membrane.skia :as backend]
         '[membrane.ui :as ui])
;; Show a window that displays a "Hello World" label
(backend/run #(ui/label "Hello World"))
Making programming more accessible is a topic I'm interested in, so if you do end up going with a non-web approach, then I would be happy to help.

👍 3



depending on your time horizon, since clojure is expression based and repl friendly, it could become a great language to build beginner friendly programming environments

🙏 3

Ill look at clojurebridge, it seems to have done many things right!


I just remember now, I started programming in QBasic (I think). We were able to put in a floppy, write a couple of lines and then see pixels on the screen.


I’m thinking of that kind of experience, but then gradually (and very friendly) building up knowldge and familiarity with programming in general and Clojure specifically.

Alex Miller (Clojure team)17:01:02 might be worth looking at too

🎉 15
👍 6
😲 3

This is very much like what I imagined but way better!

🕺 3

I've always thought the beginner persona is highly conflated (absolute beginner to programming? new to webdev? new, coming from a different lang?) For absolute beginners, webdev seems so complex, dragging so much historical baggage, fads etc that it can be just confusing to newcomers Ruby's irb console seems pretty self-contained and unassuming. Not sure if it allows one to code visual games like QBasic does though :)


That’s a very good point actually. There are very different types of approaches and beginners. Since I’m teaching designers to code, it is useful and easy for them to think in terms of layouts. Others think well in terms of abstractions/math, and then there are learners who think in terms of machinery. For the latter it is useful to start with something like C, assembly or even by constructing machines manually.


yeah I was thinking a bit about that - some people may be more 'visual-thinking' than others although I wouldn't underestimate how hard can learning the basics be: variable assignment, divide-and-conquer with functions, etc. those routinely blow children's / teens' minds so if they don't get to understand those, the rest of the learning could collapse by its own weight


Yeah, you need a lot of patience and enthusiasm to keep them hooked :)

☺️ 3

GWBasic's PLAY statement got me hooked to programming in primary school ;) (

😁 7

Seems pretty ellaborate :) I recall playing a bit with (much to the annoyance of my classmates)


yeah, also that one, both :)


Me too!!! QBasic's Sound and Play (at age 10) is when I knew I wanted to make software as a grown up.


There is no one type of programmer.


Yep. no tool, method, language or book is going to do the learning for you. That’s something each person need to figure out themselves.. eventually. “How do I learn this thing the best?“. “How do I find the relevant resources to guide my learning?” “Where do I need help?“.


In my experience the best teachers are the ones who actually try to help you to find the best learning methods for yourself.