We are getting under way with our Elixir project. I kicked the tires around Clojure, and love the abstractions, but couldn’t get over the Java ecosystem or the syntax. I am dyslexic and have never been able to make the prefix notation languages work for me. But I loved the macros and the ways you could condense your ideas.
I am starting to see those ideas really come into play. We code a few concepts. Once we start to see some repetitive themes, we decide how to condense those common idioms. Sometimes, that means building a different set of functions. Other times, macros factor heavily into the equation. Here’s an example.
CHAT BUSINESS LEVEL API
We have a chat service where rooms, topics, and other ideas are all in implemented in different processes. We have a common process model which we wrap, and that has a simple receive that looks like this:
That works great… I can dial right in to the message I want to match through pattern matching. But look at the amount of noise in that function head:
- The def
- The conn and s parameters which are always the same.
- The heavier key/value syntax
- The type match will always be first and most important, but it’s lost in the map syntax
We can improve that api significantly:
Beautiful. A four line macro makes my intentions perfectly clear. I call out the action and message type much more clearly: I am receiving the start message.
WORTH THE COST?
I know that some readers will believe that macros are some type of radioactive jar of mayonnaise that’s been in the sun three hours too long. You can probably recite the objections by heart. If not, let me help.
- This code will be hard to debug, or hide subtle bugs. (This objection perhaps ignores the bugs that I can inject by typos that impact my pattern match.)
- Macros are dangerous because they are not explicit. (This objection has merit if there’s too much going on, but not for such a simple macro.)
- Macros lead to code that is hard to extend. (This objection ignores the fact that we still allow the earlier form of this statement.)
But consider this. I’ll need to write that code, or some form of it, several hundred times for this application, and maybe several thousand. I’ll need to read that code even more. My guess is that through selective use of macros like this one, we’ll move much more quickly, make fewer mistakes, and make training new developers much simpler.
Over the coming weeks, you’re going to see us play a similar set of games to improve the way we test.
What do you think?