This is a bunch of ideas for macros that I know I’m never going to get around to implementing, but I would find insanely useful if anyone else did.
Partial in Clojure works, but it’s slow. You can tell this by the number of times you see functions that return other functions, rather than applying partial. What you really want is to declare a function once and get the partials declared for you. e.g.
(defn-partial wrap-authenticated [handler request]
(handler (assoc request :user (get-user request)))
gets rewritten as
([handler request] (handler (assoc request :user (get-user request))
([handler] (fn [request] (handler (assoc request :user (get-user request))))
A better solution would be, of course, to fix the performance of partial, but that’s a lot harder.
There’s a harder version of this: to evaluate the function up to the point it needs the unprovided parameters. But just the basic version would be a performance win.
C# implements generators like those in Python. However, it’s worth noting that the feature is entirely supported by the compiler, there’s no MSIL level implementation. The function gets written as a state machine. To go purely functional, you’d probably want to do it by constructing a sequence of (value, continuation) pairs and then calling (map first coll) on that. Obviously, you’d want to support all Clojure special forms.
Await is a new feature of C#, but that’s no reason Clojure can’t have it. It’s already been done for CoffeeScript. If you really want to be flash, implement generators and await using the same code.
One thought on “Clojure Macro Challenges #1”
I’ll admit to not really understanding monads, but as I understand it, there are basically two parts, "turn into monad" and "turn back out". You could probably create def-monad, which did some standard things in transforming standard clojure syntax to a monad, and the def-generator and def-async construct the monad and then resolve it back out. Hopefully with excellent performance… :)But as I say, I don’t really understand monads. I understand that they’re powerful, but I don’t really understand how to use them or the performance implications of using them.