Senior Software Engineer || Full-stack

Senior Software Engineer || Full-stack

Amperity | Seattle, WA
Largest clojure shop in Seattle
100000 - 150000

At Amperity, we love Clojure, so much that we use it full stack. Join us and you'll be using Clojure, ClojureScript, and modern big data tools, such as Mesos and Kafka to build systems that use machine learning to address one of the largest unmet needs in the marketing technology space. Our team includes top Clojure developer Mike Fikes, creator of the ClojureScript REPL Planck, so if you're looking to work with talented colleagues then look no further. Full Press Release.

Technologies we use:

  • Clojure for back end services
  • ClojureScript for our front end, a reactive SPA
  • Big data tools, including Mesos, Spark, Kafka and Accumulo
  • Modern provisioning infrastructure, including Apache Aurora and SaltStack

Interesting problems:

  • Our system involves ingestion of very large amounts of data, and blending this processing with real-time events
  • We automatically stitch data together across disparate systems, and improve this process in generalized ways
  • We allow users to perform complex, real-time queries across aggregated datasets

About you:

  • You are excited about using Clojure in a production environment, and have experience with Clojure or other functional languages
  • Experience building JVM oriented production systems
  • Experience working with large scale data oriented systems
  • Your ears perk up when somebody says "graph traversal"
  • Open minded, inclusive, and motivated to make good decisions


Scripting vs. Engineering

I’ve come to the conclusion that the terms “programming” and “coding” have become horribly ambiguous which has enabled:

  • organisations to offer courses on html/css editing as “coding”
  • people to make claims like “nodejs is more productive than java” (which is a nonsense statement either way)
  • various arguments along the lines of “is X a PROPER programming language”.

I think it’s more helpful to think in terms of “scripting” vs. “engineering”:

  • Scripting is geared towards the short-term, small team or solo, quick prototyping.
  • Engineering is geared towards the long-term, larger teams, maintainability(i.e. readability), refactorability and extensibility.

It’s probably impossible to agree on whether a language is “scripting” or “engineering”, but obviously I have personal opinions about some characteristics of each:

  • In the long term, the time taken writing software is 90% reading what’s already there. Languages that don’t support readability (or IDE analysis support) fall towards the Scripting end. IMHO the reason nodejs has encouraged microservices is because nodejs is quickly unreadable – you don’t extend a nodejs app, you just write another service…
  • Monkey-patching automatically precludes a language from Engineering (it violates the Principle of Least Surprise) – how can anyone reason about code that can extend an object’s methods at runtime?
  • Static-typing moves the language towards Engineering by increasing correctness and readability. Completely pathological strict typing languages like Haskel may be a learning barrier though (along with Haskel programmers’ irresistible temptation to use punctuation as function names it seems – quick, quick, tell me what the difference is between foldl and foldl’)
  • If the language has static typing then good type inference cuts down on the boilerplate. These days I wouldn’t write any Java without using lombok.
  • Immutable objects are good Engineering. Likewise functional languages can aid Engineering, except that the temptation towards one-line-itis reduces readability.
  • Encapsulation and clear techniques for Dependency Injection help Engineering as it supports mocking in unit tests.
  • Automatic resource management aids Engineering.

So I can possibly come up with a completely unscientific and arrogantly self-opinionated table of languages: 5 is good, 1 is bad (if the square is blank then I haven’t formed an opinion):

Readability Least surprise Static types Type inference Immutable/Functional DI/Mocking Resource Management
Java with lombok 4 4 4 3 2 5 3
(“try” with resources)
Kotlin 4 4 4 5 4 5
Ceylon 4 4 5
(inline Union types look interesting)
5 5
Rust 5 5
Clojure 3 3
(things get turned into null at the drop of a hat)
1 3 5 5 4
Python 4 4 3
Python with Coconut 5
Javascript 3 3 0 4 0
(everything is in a global namespace)
Bash (just for fun) 4 3
(space handling in values)
0 0 0 0 4
(can’t hold on to anything for long)


Scripting vs. Engineering databases

I think we can extend this to databases too. The NoSQL/schema-less fashion of databases are definitely up the scripting end:

“The problem is that in the absence of a formal schema, the “schema” is an emergent property which is reflected in the code used to manipulate the database” – comment in Why You Should Never Use MongoDB

The “MEAN stack” – mongodb, express, angular and nodejs – is certainly for prototypes only. It should be called the WONGA stack: Write Only Node and anGulAr (possibly only UK readers will get the reference). Angular and React are good for “single page application” building, though possibly vastly improved by using typescript (and flow) instead of javascript.

Responses to “static typing is bad / gets in the way”

The post “Static vs. Dynamic” Is the Wrong Question for Working Programmers makes the correct statement “[static typing benefits] Proof that certain kinds of dynamic errors are impossible” but I suggest the supposed “drawbacks” are incorrect:

  • Increased verbosity or reduced expressiveness – not true if the language has good type inference, and type annotations improve readability immensely.
  • Rejection of otherwise correct programs – how can a program be correct if it has a type error? See how an uninitialised variable cost $90,000.
  • Slower programmer iteration (possibly lengthy compile/run cycles) – IDE integration and incremental builds removes this completely
  • A need for the developer to learn “static typing” language feature – I’d suggest that if you really know what your program is doing then you do know about types (unless you’re programming in the Stringly style)


What the Hell is Symbolic Computation?

I’ve been reading a lot of Lisp books lately, some more advanced than others. All of the introductory books I’ve seen cover the idea of symbolic computation, but most of them breeze past it with just a few pages about “symbols” and “quoting”. For many programmers coming from non-Lisp languages these are new, foreign concepts that don’t really map back to anything in their previous experience. But the books seem to expect you to understand this things after just a couple of paragraphs.

One book that does spend more time on this is the appropriately-named Common Lisp: A Gentle Introduction to Symbolic Computation. If you’re looking for a good introductory Lisp book, that’s the one I’d recommend. However, it’s quite a long book and starts at the very basics (you don’t even write code for the first few chapters — you program with drawings). If you already know the some Lisp then you might find yourself bored if you go through the entire thing just for the symbolic computation bits.

This post is an attempt to explain what symbols actually are and what quoting does. You’ll get the most out of it if you’re already familiar with the basics of Lisp (i.e. you aren’t scared by the parentheses). But if you already know what something like this would print, you’ll probably be bored:

(let ((foo ''a))
  (print foo)
  (print 'foo)
  (print (car foo))
  (print (cdr foo)))


Before we start I’ll get this warning out of the way: I’m going to gloss over a lot of gory details to get at the important core ideas.

When I say “this thing is implemented like so” it’s safe to assume that in reality things are messier and more complicated and will vary between implementations and dialects. My goal is to give you some intuition for the basic ideas, not to exhaustively cover how a particular implementation works.

I’ll be using Common Lisp for the examples, but the concepts apply equally to Scheme, Clojure, and other Lisps too.

With that out of the way, let’s dive in!


The Read-Eval-Print-Loop that so many languages these days have built-in is a good place to start in our exploration. You’re probably familiar with the idea of a REPL from languages like Python, Ruby, Javascript, etc. In Python it looks like this:

$ python
>>> if True:
...     print "Yes"
... else:
...     print "No"

A handwavey definition of a REPL could be something like this:

A REPL is a program that lets you type in code. It runs that code, prints out the result, and loops back to the beginning to let you type in more.

This is a good first start, but to understand symbols we’re going to need to get a much clearer, more precise handle on what exactly each letter in “REPL” means. We’ll start backwards and outside-in with the simplest component.


The “L” in “REPL” stands for “Loop”, and it’s the easiest part to understand. A REPL doesn’t just process one bit of code and then exit, it loops forever (or until you tell it to quit).

There’s not a lot to say here, except that we’ll go ahead and lump together the extra busywork a REPL needs to do into this step so we can ignore it for the rest of the post. This includes things like:

  • Printing the nice prompt at the beginning (>>> or ... in Python).
  • Checking for Ctrl-D to quit.
  • Handling exceptions (so they don’t kill the process).


The next letter is “P” for “Print”. Like loop this should be familiar territory, but let’s nail down exactly what it does. The job of the print function is to:

  • Take as input some kind of object/data structure in memory.
  • Produce some series of characters (a string) that represent this object.
  • Write those characters somewhere (standard output, a text panel in a GUI, etc).

For example: if we give the integer 1 to Python’s print, it produces a string of two characters (the digit 1 and a newline) and writes it to the terminal. There are a lot of little details that aren’t important here (line endings, string encoding, where the output actually goes, etc). The important part that you should fix in your mind is this:

print takes an object, converts it into a string, and outputs it.

Note: I’ve called print a function here, and I’ll do the same for read and eval later on. This is correct for Common Lisp, but not necessarily for languages like Python or Javascript. For the purposes of this post you can just imagine them as functions and realize that in the real world they’re more like “phases” that have a lot more complex machinery under them.


We’ll jump over to the other side of the acronym now. “R” is for “Read”, and this is where things start to get tricky.

In most non-Lisp languages the “read” and “eval” phases of the REPL tend to get blurred together, but if you want to understand symbolic computation in Lisp you absolutely must keep these two parts cleanly separated in your mind.

We can define read as almost the polar opposite of print. read is a function whose job is to:

  • Take as input a string of characters from some source.
  • Decode” that string and produce some kind of object in memory.
  • Return that object.

Notice how this mirrors print:

  • print: Object → Characters
  • read: Characters → Object

This is the second definition you need to fix in your brain:

print takes an object, converts it into a string, and outputs it.
read takes a string, converts it into an object, and returns it.

If we read in the string 1.0 (that’s three ASCII characters), we’ll get some kind of floating point number object back. Sometimes there are many ways to represent the same object in memory. For example: reading the strings 1.0 and 1.0000 will both produce equivalent floating point objects representing the number “one”.

Side note (if you’re not feeling pedantic feel free to skip this): the word “equivalent” here is a bit tricky. When you read two strings like 1.0 and 1.000 you might get back two pointers to the same hunk of memory, or you might get back two pointers to two separate hunks of memory, or even just a machine word representing the floating point number directly. It depends on the language (and even the implementation). What I mean by “equivalent” is that there’s no way to tell which value came from which input. You can’t say “this hunk of memory must have come from the string 1.000” because read has “sanitized” the input by that point.


So now we’ve got read, print, and loop. read takes characters from a stream and produces objects, and print takes objects and produces characters and writes them to a stream. We’re still missing a letter, but what would happen if we just hook these three up together right now?

CL-USER> (loop (print (read)))
> 1
>    1.0
> 1.00000

I’ve added a little > prompt to the output here to make it clear where I’m typing.

Essentially what we’ve got here is a little pretty-printer! Notice how things like extra whitespace and useless zeroes got stripped out. This isn’t terribly useful, but at least it’s doing something.

However, it’s important to realize where the “prettifying” actually happened: read actually did the hard work! By the time print got its grubby little paws on those one-point-zeroes the extra whitespace and digits were long gone. Maybe we should give credit where it’s due and call this a “pretty-reader” instead.

Reading Other Data

Up to this point I’ve been using numbers as examples because they’re simple, but of course we can read and print lots of other kinds of things. Lists and strings (and lists of strings!) are some common examples:

CL-USER> (print (read))
> ("hello"       "world")
("hello" "world")

$ python
>>> [    "hello"  , "world"]
['hello', 'world']

There are lots of other kinds of things you can read and print, depending on the particular language. What’s important here is the strict separation of read and print.

Readable Printing

Before we move on, one thing we should talk about is the idea of “readable printing”. This idea becomes clear almost immediately when you work at the Python REPL:

$ python
>>> "foo\nbar"
>>> print "foo\nbar"

Why was the first string printed with quotes and an escaped newline, and the second without quotes and an actual newline?

When we defined print earlier, one of the steps was:

  • Produce some series of characters (a string) that represent this object.

Much like there are many character strings that result in the same object (e.g. 1.0 and 1.000) there are often many ways we can represent a particular object as a series of characters. For example: we can represent the number two as 2, or 10 in binary, or two in English. We can represent a string as the actual characters in it, or we could represent it “escaped” like Python does in the first line.

The core idea here is that of “readable printing”: printing the characters you would need to give to read to produce this object.

This is different from what I’ll call “aesthetic printing”: printing characters for this object which look nice to a human.

In Python these two kinds of printing are seen in the separate __str__ and __repr__ methods. In Common Lisp it’s controlled by the *print-readably* variable. Other languages have different mechanisms.

Reading Non-Lisp

So we know how reading and printing data works, but you can do more than that at a typical REPL. Let’s revisit the first Python example:

$ python
>>> if True:
...     print "Yes"
... else:
...     print "No"

We know that read takes a series of characters and turns them into an object. When we read this series of characters, what comes out the other end? For most languages (Python, Ruby, Javascript, Scala, etc) the answer is some kind of abstract syntax tree represented as a data structure. You might imagine something like this buried deep within the guts of the Python interpreter:

class IfStatement(ASTNode):
    def __init__(self, test_node, then_node, else_node):
        self.test_node = test_node
        self.then_node = then_node
        self.else_node = else_node

The details would surely be a lot hairier in the real world, but the general idea is that the stream of characters representing your code gets read in and parsed into some kind of data structure in memory.

This is all well and good, but our example printed “Yes”, which certainly isn’t a representation of an AST node. Where did that come from? To answer that we’ll need the final letter in the acronym.

Evaluating Non-Lisp

The “E” in REPL stands for “Eval”.

This is the last time we’ll consider Python in this post, because we’re about to move past it to more powerful ideas. In Python, the purpose of the eval phase of the REPL is to:

  • Take an AST node (or simple data) as input.
  • Run the code (also known as evaluating it).
  • Return the result (if any).

This is fairly straightforward, at least for our simple if statement. Python will evaluate the test_node part of the if, and then evaluate one of the other parts depending on whether the test was truthy or falsey.

Of course the actual process of evaluating real-life Python code is much more complicated than I’ve glossed over here, but this is good enough for us to use as a springboard to dive into the beautiful world of Lisp.

Reading Lisp

When we talked about reading the Python if statement I said that Python would parse it into some kind of data structure representing an AST node. I didn’t point you at the actual data structure in the Python source code because I have no idea where it actually is, and it’s probably not nearly as simple as the one I sketched out.

Now that we’re talking about Lisp, however, I really can show you exactly what an if statement in Lisp reads as! I’ll use read-from-string to make it a bit easier to see what’s input and what’s output, but it would work the same way with just plain old read and input from standard in. Here we go:

CL-USER> (print
           (read-from-string "(if t (print 1) (print 2))"))

(IF T (PRINT 1) (PRINT 2))

CL-USER> (type-of
           (read-from-string "(if t (print 1) (print 2))"))


Instead of some kind of AST node data structure buried deep within the heart of our implementation we get… a list! An ordinary, garden-variety, vanilla list made of good old trusty cons cells!

The list we get contains four elements, two of which are themselves lists. But what do these lists actually contain?

The numbers are simple enough — we saw them earlier. read turns a series of digits into a number somewhere in memory, and print spits out a series of characters that represent the number:

CL-USER> (type-of (read-from-string "100"))

(INTEGER 0 4611686018427387903)

The string 100 does indeed represent an integer between zero and four squillion-something.

But what are those other things in our list? The if and t and print? Are they some magic keywords internal to the guts of our Lisp that print is just outputting nicely for our benefit?

CL-USER> (type-of (read-from-string "if"))


Buckle up — it’s time to learn about symbols.


A symbol in Lisp is a simple data structure that turns out to be extremely useful. You can imagine it being defined something like this:

(defstruct symbol

The name of a symbol is a string of characters representing the symbol’s name:

CL-USER> (type-of (read-from-string "if"))


CL-USER> (symbol-name (read-from-string "if"))


Symbols get created (usually) when they are read for the first time. If you read a sequence of characters that matches the name of an existing symbol (let’s ignore the lowercase/uppercase thing for now), read just returns that existing symbol:

CL-USER> (eq (read-from-string "cats")
             (read-from-string "cats"))


Here read saw the string cats and created a new symbol somewhere in memory with CATS as its name. The second call to read-from-string read in the string cats, saw an existing symbol with the matching name, and just returned it straight away. That’s why eq returned true — the two read calls returned pointers to the exact same hunk of memory.

(read also “interned” the symbol into the current package. We’re going to ignore the package system for this post — it’s not important to the core topic. We’ll also ignore the property list.)

So to recap:

  • read is a function that takes characters and turns them into objects.
  • When you feed read certain strings of characters (i.e. without special characters), it returns a symbol object whose name matches those characters (creating it if necessary).
  • Symbols are just normal Lisp data structures with a few specific fields.

So what does print do with a symbol? It just prints the name!

CL-USER> (print (read-from-string "cats"))


Simple enough. Note that this is readably printed — if we feed it back to read we’ll get an equivalent symbol back (the exact same symbol, in fact).

But wait! If we read symbols in and they’re just normal vanilla structures, then how do we actually do anything in Lisp? How does anything actually run?

Evaluating Lisp

Now we need to go back to eval. In the Python example I handwaved a bit and said that eval “ran the code” but didn’t really explain how that happened. Now that we’re in the warm embrace of Lisp we can nail things down a lot more cleanly.

eval (in Lisp) is a function whose job is to:

  • Take an object.
  • Do something useful with it to get another object.
  • Return the resulting object.

I know, I know, that seems as clear as a brick. But if we can actually define what “something useful” means it will be a lot more helpful. Lisp’s eval follows a few simple rules to produce its output.

Strings and Numbers

First of all, eval will just pass numbers and strings straight through without touching them at all:

(defun eval (thing)
    ((numberp thing) thing)
    ((stringp thing) thing)
    ; ...
    (t (error "What the hell is this?"))))

This makes sense because there’s not a lot more useful stuff you can do with a number or a string on its own. I suppose you could write a language where the evaluation phase ran all numbers through the absolute value function because you wanted to remove all negativity from programming or something, but that seems a bit esoteric.

Basic Lists

What about lists, like our friend the if statement (a list of four things)? Well the first thing anyone learns about Lisp is the funny syntax. In most cases, when passed a list eval treats the first element as the name of a function, and the rest as the arguments. It will evaluate the arguments and call the function with them:

(defun eval (thing)
    ((numberp thing) thing)
    ((stringp thing) thing)
    ((typep thing 'list)
     (destructuring-bind (head . arguments) thing
       (apply (symbol-function head)
              (mapcar #'eval arguments))))
    ; ...
    (t (error "What the hell is this?"))))

At this point we know enough to understand exactly what happens when we say something like (+ 1 2) at a Lisp REPL!

  • Lisp reads the seven characters we gave it, which becomes a list of three objects: the symbol +, the integer 1, and the integer 2.
  • Lisp passes that three-object list to eval.
  • eval looks up what is in the function slot of the symbol at the front of the list (that symbol is +).
  • The symbol + was helpfully given a function by the Lisp implementation (run (symbol-function (read-from-string "+")) to confirm that I’m not lying to you).
  • Lisp evaluates each item in the rest of the list. In this case they’re each a number, so each one evaluates to itself.
  • Lisp calls the function with the evaluated arguments to get a result (in this case: the integer 3).
  • Lisp passes the result to print, which turns it into a string of characters (one character, in this case) and prints it to standard out.

Whew! That seems like a lot, but each piece is pretty small. Go slowly through it and make sure you really understand each step in the preceding list before you move on.

If you don’t believe me that this is really how it works, try this:

CL-USER> (setf (symbol-function (read-from-string "square"))
               (lambda (x) (* x x)))


CL-USER> (square 4)


We set the function slot of the symbol square to be a function that squares its argument, and then we can run it like any other function.

Trace through the evaluation of that last (square 4) call before moving on.


What about symbols that aren’t at the front of a list? For example:

CL-USER> (defvar ten 10)


CL-USER> (square ten)


In this case, everything proceeds as it did before until the recursive call to eval the argument to square. The argument is just a bare symbol (not a number or a list or a string), so we need another rule in our eval function:

(defun eval (thing)
    ((numberp thing) thing)
    ((stringp thing) thing)
    ((symbolp thing) (symbol-value thing)) ; NEW
    ((listp thing)
     (destructuring-bind (head . arguments)
       (apply (symbol-function head)
              (mapcar #'eval arguments))))
    ; ...
    (t (error "What the hell is this?"))))

If eval sees a symbol on its own, it will just return whatever is in the value slot of the symbol data structure. Simple enough!

Special Forms

If course there are a few things we haven’t talked about yet. First of all: there are some “magic” symbols that aren’t functions, but are hardcoded into the evaluation function to do certain things. In Common Lisp they’re called “special operators” and there are twenty-five of them.

Let’s add a special rule to our eval function to handle one of them (our old friend if):

(defun eval (thing)
    ((numberp thing) thing)
    ((stringp thing) thing)
    ((symbolp thing) (symbol-value thing))
    ((listp thing)
     (destructuring-bind (head . arguments) thing
         ((eq head (read-from-string "if")) ; NEW
          (destructuring-bind (test then else) arguments
            (if (eval test)
              (eval then)
              (eval else))))
          (apply (symbol-function head)
                 (mapcar #'eval arguments))))))
    ; ...
    (t (error "What the hell is this?"))))

At this point your head might be starting to hurt. How have we just used if to define itself? Is anything here actually real, or is Lisp just a serpent eating its own tail forever?

An Ouroborromean Paradox?

If the “metacircularity” (god, I hate that word) of what we’ve just done bothers you, remember that this eval function here is just a sample of how you can write it in Lisp. You could also write it in some other language, like C or Java (see: ABCL) or really anything. That would let you “bottom out” to something that’s not Lisp.

But really, is that any less circular? You still need some language to run the thing! Why does an eval written in C seem less “cheaty” than one written in Lisp? Because it compiles to machine code? Try (disassemble #'sb-impl::simple-eval-in-lexenv) in SBCL and you’ll get a few thousand bytes of x86 assembly that was originally some Lisp code much like ours.

My advice is to just let it flow over you, even if you feel a bit uneasy at the sight of something like this. Eventually as you become more at home in your chosen Lisp, writing high-level code one moment and disassembleing a function the next, you’ll make peace with the serpent.


There are quite a few things in eval that we haven’t covered here, like the other twenty-four special operators, lexical variables, lambda forms, and more. But this should be enough for you to wrap your head around symbols and how they’re used in Lisp.

Before we move on to the final part of this story, make sure you can figure out the answers to these questions:

  1. What does the single character 1 read as? What does it evaluate to?
  2. What do the characters "hello\"world" read as? What do they evaluate to? How would the result be printed readably? How would the result be printed aesthetically?
  3. What do the characters (list (+ 1 2) ten) read as? What does it evaluate to? How does each step of the evaluation work? Trace out each of the calls to eval on paper, with their arguments and their results. What does the final result print as?
  4. Use symbol-function to see what’s in the function slot of the symbol car. How does your Lisp print that thing?
  5. Try to look up the function slot of a symbol without a function. What happens?
  6. Use symbol-function to see what’s in the function slot of the symbol if. What happens? Does that seem right? If so, why?
  7. Go to the HyperSpec page for symbol and search for “the consequences are undefined if”. Try all of those things and find out what interesting things break in your Lisp.

If you’re not using Common Lisp, port these exercises to your language.


Up to now we’ve been using the clumsy (read-from-string "foo") form to get ahold of symbols, but there’s an easier way called “quoting”.

Quoting often confuses new Lisp programmers, and they’ll end up randomly adding/removing quotes to something until it appears to do what they want. Now that you’ve got read, eval, and print firmly separated in your mind, quote will be much easier to understand.

The Special Operator

Quoting actually has two distinct components: one that affects read and one that affects eval. In most books the distinction between these two only gets barely a sentence or two, which is probably why beginners are so confused. Let’s look at the eval side of things first.

quote is one of the twenty-five special operators. All it does it pass its (single) argument back from eval untouched. Normally the argument itself would have been evaluated, but quote prevents that:

(defun eval (thing)
    ((numberp thing) thing)
    ((stringp thing) thing)
    ((symbolp thing) (symbol-value thing))
    ((listp thing)
     (destructuring-bind (head . arguments) thing
         ((eq head (read-from-string "if"))
          (destructuring-bind (test then else) arguments
            (if (eval test)
              (eval then)
              (eval else))))
         ((eq head (read-from-string "quote")) ; NEW
          (first arguments))
          (apply (symbol-function head)
                 (mapcar #'eval arguments))))))
    ; ...
    (t (error "What the hell is this?"))))

I know that seems strange, but let’s look at it in action:

CL-USER> (+ 1 2)


CL-USER> (quote (+ 1 2))

(+ 1 2)

Our first example is the same one we used in the previous section:

  • read takes in seven characters and returns a list of three items: the symbol + and two numbers.
  • eval gets the three-element list, looks up the function for the symbol +, recursively evaluates the arguments (which evaluate to themselves), and applies the function.
  • print gets the integer 3, turns it into ASCII, and writes it to the terminal.

The second example uses quote:

  • read takes in fifteen characters and returns a list of two items: the symbol quote and a list of three items (the symbol + and two numbers).
  • eval gets the three element list and notices that the first element is the special operator quote. It simply returns the second element in the list untouched, which in this case is a list of three items.
  • print gets that three element list, turns it into seven characters, and writes it to the terminal.

Just for fun, let’s ride the serpent and use quote in the definition of itself inside eval to clean things up a bit:

(defun eval (thing)
    ((numberp thing) thing)
    ((stringp thing) thing)
    ((symbolp thing) (symbol-value thing))
    ((listp thing)
     (destructuring-bind (head . arguments) thing
         ((eq head (quote if))
          (destructuring-bind (test then else) arguments
            (if (eval test)
              (eval then)
              (eval else))))
         ((eq head (quote quote)) ; WHAT IN THE
          (first arguments))
          (apply (symbol-function head)
                 (mapcar #'eval arguments))))))
    ; ...
    (t (error "What the hell is this?"))))

That (quote quote) looks just completely bonkers, right? Step through it piece by piece to figure it out:

  • What do the five characters quote read as? What do they evaluate to?
  • What do the thirteen (spooky!) characters (quote quote) read as? When eval gets its hands on that, what clause in the cond does it hit? What does that return?

Try these in a Lisp REPL if you’re not 100% sure of the answers. The functions read-from-string, eval, and type-of will come in handy.

The Read Macro

Now let’s look at the final piece of the puzzle. ' (that’s a single ASCII quote character) is a read macro. Don’t worry if you don’t know exactly what that means right now. The important part is that when read sees a quote character, it returns a two-element list containing the symbol quote and the next form, which is read normally.

The four characters 'foo go into read and come out as a two-element list containing: the symbol quote and the symbol foo. Again, because it’s important: this happens at read time. By the time eval sees anything it’s already been turned into that two-element list.

It can be a bit slippery to get a grip on this, because print will “helpfully” print a list of (quote whatever) as 'whatever! But we can use trusty old car and cdr to see what’s really going on:

CL-USER> (read-from-string "'foo")


CL-USER> (type-of (read-from-string "'foo"))


CL-USER> (car (read-from-string "'foo"))


CL-USER> (cdr (read-from-string "'foo"))


That’s really all there is to it: 'form is returned by read as (quote form). Then that gets passed along to eval, which sees the quote special operator and passes the argument back untouched.

Note that form doesn’t have to be a symbol:

  • '(1 2 (4 5)) reads as (quote (1 2 (4 5)))
  • '150 reads as (quote 150)
  • '"hello" reads as (quote "hello")
  • '(if if if if) reads as (quote (if if if if))


That pretty much wraps up quote. Once you’ve cleanly separated read, eval, and print in your mind it becomes a lot less mystical (or perhaps more, depending on your point of view).

If you want to twist your brain just a bit more, try these exercises:

  1. What do the characters foo read in as? What do they evaluate to? How does it print?
  2. What do the characters 'foo read in as? What do they evaluate to? How does it print?
  3. What do the characters ''foo read in as? What do they evaluate to? How does it print?
  4. What do the characters '1.0 read in as? What do they evaluate to? How does it print?
  5. What do the characters '(1 2 3) read in as? How many elements are in the list? What does it evaluate to? How many elements are in that list?
  6. Update our implementation of eval to use the ' read macro instead of quote.
  7. Certain symbols like t and nil are special — they evaluate to themselves like numbers or strings. Add this to eval.
  8. What do the characters nil read in as? What is the type of that object? What do they evaluate to? What type is that result?
  9. What do the characters 'nil read in as? What is the type of that object? What do they evaluate to? What type is that result?
  10. What do the characters ''nil read in as? What is the type of that object? What do they evaluate to? What type is that result?

A Quick Recap

If you’ve gotten this far and understood everything, you should have a good grasp of how symbolic computation works. Here are the main things I hope you’ve taken away from this post:

  • read, eval, and print are three separate, distinct functions/phases in the interpretation of Lisp (and really all (okay, most)) code.
  • Keeping these three phases clearly separated in your mind will make it easier to understand symbols and quoting in Lisp.
  • Symbols are nothing magic, they’re just a particular data structure with a couple of fields.
  • The important thing is how read and eval treat symbols. That’s where the magic happens.
  • quote is just a “short-circuit” in eval that turns out to be really useful.
  • ' is just a lazier way of writing (quote ...).

Where to Go From Here

Now that you’ve got a firmer grasp on what the hell symbols actually are, there are a lot of cool things you might want to check out that will show you what you can do with them:

  • Reread some of your introductory Lisp books again, seeing if things seem to make a bit more sense now.
  • Read about backquote/quasiquote. How does it compare to the quote we explored here?
  • Read Paradigms of Artificial Intelligence Programming and pay attention to how Norvig uses symbols for various tasks. Also pay attention to what he says about property lists, because we skipped them here.
  • Read the guide to the Common Lisp package system to learn all the stuff I left out about the Common Lisp package system.
  • Gaze upon this macro in wonder (or horror).
  • Read the HyperSpec pages for things like symbol and quote.
  • Find and read your Lisp implementation’s eval function.
  • Find and read another Lisp implementation’s eval function.
  • Watch the SICP Lectures on YouTube.


Senior Software Engineer (Haskell) at Front Row Education (Full-time)


Senior Functional Web Engineer to join fast-growing education startup transforming the way 3+ million K-8 students learn Math and English.

What you will be doing

Architect, design and develop new applications, tools and distributed systems for the Front Row ecosystem in Haskell, Flow, PostgreSQL, Ansible and many others. You will get to work on your deliverable end-to-end, from the UX to the deployment logic.

Mentor and support more junior developers in the organization

Create, improve and refine workflows and processes for delivering quality software on time and without incurring debt

Work as part of a very small (there's literally half a dozen of us!), world-class team of engineers with a track record of rapidly delivering valuable software to millions of users.

Work closely with Front Row educators, product managers, customer support representatives and account executives to help the business move fast and efficiently through relentless automation.

Why you should join Front Row

Our mission is important to us, and we want it to be important to you as well: millions of students learn math using Front Row every month. Our early results show students improve twice as much while using Front Row than their peers who aren’t using the program.

As an experienced engineer, you will have a massive impact on the company, product, and culture; you’ll have a ton of autonomy and responsibility; you’ll have equity to match the weight of this role. If you're looking for an opportunity to both grow and do meaningful work, surrounded and supported by like-minded professionals, this is THE place for you.

You will be working side by side with well known world-class personalities in the Haskell and Functional Programming community whose work you've likely used. Front Row is an active participant to the Open Source community and contributor to some of the most popular Haskell libraries.

A lot of flexibility: while we all work towards the same goals, you’ll have a lot of autonomy in what you work on. You can work from home up to one day a week, and we have a very flexible untracked vacation days policy

The company and its revenue are growing at a rocketship pace. Front Row is projected to make a massive impact on the world of education in the next few years. It's a once in a lifetime opportunity to join a small organization with great odds of becoming the Next Big Thing.

Must haves

  • You have experience doing full-stack web development. You understand HTTP, networking, databases and the world of distributed systems.
  • You have functional programming experience.
  • Extreme hustle: you’ll be solving a lot of problems you haven’t faced before without the resources and the support of a giant organization. You must thrive on getting things done, whatever the cost.
  • Soft skills: we want you to move into a leadership position, so you must be an expert communicator


  • You have led a software development team before
  • You have familiarity with a functional stack (Haskell / Clojure / Scala / OCaml etc)
  • You understand and have worked all around the stack before, from infrastructure automation all the way to the frontend
  • You're comfortable with the Behavior-Driven Development style
  • You have worked at a very small startup before: you thrive on having a lot of responsibility and little oversight
  • You have worked in small and effective Agile/XP teams before
  • You have delivered working software to large numbers of users before


  • Competitive salary
  • Generous equity option grants
  • Medical, Dental, and Vision
  • Catered lunch and dinner 4 times a week
  • Equipment budget
  • (onsite only) One flexible work day per week
  • (onsite only) Working from downtown SF, very accessible location
  • Professional yet casual work environment

Get information on how to apply for this position.


The New Normal: Data Leverage

Like many developers, I’ve spent a lot of time thinking about objects. I started doing object-oriented programming (OOP) in 1989, and was arguably still doing it up until 2012. The concept of objects arose in GUIs and simulations, where it is natural to think about sending message to things. Over time though, the idea of messages took a back seat to the idea of locking data up in little containers where each class provides a namespace of functions to operate on it.

With OOP, classes hide all the data. Every object provides its own methods on the class, which makes up a library for what you’re allowed to do with that class—but only that class. It doesn’t give you great functions that work across everything.

Working with databases from an object-oriented language leads you to create object relational mapping layers. That is essentially inserting a tool that knows how to work with objects in order to get data out of them and into the database. This tool calls the right methods on those objects to get the data out, creates an insert statement for the relational database and puts the data in the statement.

Looking at this now, we can see that this entire complex layer of software only exists because we chose to keep our data in objects. Our object relational map tool is a solution to a problem that we created. And, we created the problem because we were embedded in an old paradigm.

The New Paradigm: Data Orientation

Porsche, Emily Baron,

Porsche, Emily Baron,

The majority of our work is with data. Services accept data on the wire, process it and either put it in a database or put the transformed result back on the wire. The whole approach of OOP - writing and annotating classes rather than simply working with the data as data - introduces fragility into the system. In contrast, working with data as pure data streamlines development and enables change. Data orientation powers the new, maneuverable microservices architectures.

For example, in Clojure, you deal with data as data. You don’t try to force the data into an object-oriented semantic. Clojure has functions that work on any kind of sequential data, any kind of associative data and any kind of set data. Instead of writing a class that has ten or fifteen methods, you get to use hundreds of functions. (Over 640 in clojure.core alone.) 

So, it doesn’t matter if you’re using a map to represent a customer or an order or an order line item, you use the same functions to operate on all of them. The functions are more general, so they are more valuable because you can apply them more broadly.

When you first start working with Clojure, you’ll be tempted to bring along some of the OOP baggage. But it’s a good idea to stop and rethink what it is you want to do. You need to reconsider why we did certain things in the OOP world, and whether we need to continue doing them in a data-oriented world.

To demonstrate the contrast, here’s an example of what you might do to add a new table if you’re working with a relational database. You put together a string that says something like:


The string buries the data. The data is no longer available for further processing. Once the data is in the string, I can't do anything with it except send it to the database server. String bashing opens the door to security vulnerabilities. Strings create fragility. As if that weren't enough, the time and energy it takes to generate strings only to have the database parse them is wasted. The process only exists because I can’t directly send the database the attributes that I want to create. 

The same thing in Datomic looks like this:

[{:db/id          #db/id[:db.part/db]
  :db/ident       :foo/id
  :db/valueType   :db.type/long
  :db/cardinality :db.cardinality/one
  :db/unique      :db.unique/identity
  :db/doc         "Unique identifier for Foos."
  :db.install/_partition :db.part/db}
 {:db/id          #db/id[:db.part/db]
  :db/ident       :foo/name
  :db/valueType   :db.type/string
  :db/doc         "A human-readable name for a Foo."
  :db/cardinality :db.cardinality/one
  :db.install/_partition :db.part/db}]

You can take a look at the schema reference if you're interested in the details.

To me, the most interesting part is what I can do with that metadata. In most databases, data and metadata are entirely separate worlds. You've got one language for manipulating the database schema and a totally different one for manipulating the contents of the database. The query language can only query contents and cannot touch schema. Datomic puts data and metadata on the same level. Suppose I wanted to make a documentation generator that ran across my code and documented the schema. Can you imagine scanning for every string, then parsing the string to see if it is a SQL statement, then extracting the details of the tables? Absolutely not. Can you imagine mapping a function across a list of maps, to extract the :db/ident and :db/doc keys? Easiest thing in the world.

This is why I like working with Datomic. My transaction is data, just a vector of vectors or a vector of maps. What I get back as a result is data, a set of tuples. If I want to look at any of the built-in attributes of any of the attributes I’ve added—any of the metadata—I just do an ordinary query and get back ordinary data. My query is specified as data. Results come back as data. 

I eliminate the loop of generating and parsing strings. I can use data in my program and send the data directly to the database. This creates a great simplicity:  I never need an object relational mapping layer. If I need to look at something, I can interact with it through the REPL or through a debugger and I just see the data, I don’t see some opaque driver-specific object like I would with JDBC.

Data Orientation Facilitates Change

Data orientation comes into play when we’re building services or interacting with services. Anytime we need to use JSON or XML to communicate with something, the typical approach in Java or C# is to write a class that represents the unit of data that we’re passing around. This is when versioning gets difficult and people say, “it's hard to support multiple versions of your API.” Again, it’s a problem we’ve created for ourselves by choosing the object-oriented approach. Working with data as data, it becomes easier to work with multiple versions, and easier to manage change, which builds antifragility.

With Clojure, it’s very easy to support multiple versions of our API. In fact, it so easy, we can even have an API about APIs. Now, our data-orientation approach takes everything up a level. By using data rather than classes or annotations we give ourselves the ability to “go meta” with no more difficulty than writing things (straight?). If we wanted to do that in Java, we would need to build some kind of a new language that emitted Java as its byte code. We don’t need to do that with Clojure.

By focusing on the data, and not to doing a lot of the data modeling inherent in the old OOP paradigm, the data becomes very easy to represent, open up and unlock. For example, it’s easy to make the data available to mobile and web applications used by other systems via APIs.

The Power of Data-driven Microservices

With a data-driven microservice, instead of writing code that describes the data that you’re going to send via JSON, or writing code that has annotations all over it to turn it into REST paths, we simply send a chunk of data to a service. That data describes a data format and it describes end points to expose via http (nonREST). This data orientation paves a direct path to maneuverable microservices and increased business value.

In a previous post, I asserted that by working with a maneuverable microservices architecture and open source technology and tools such as Clojure and Datomic, a pair of skilled developers could create a meaningful service in minutes or hours versus days and weeks.  

My colleague Paul deGrandis has done some compelling work in the area of data-driven microservices. Working with Consumer Reports, who was in the process of reviewing new technologies and platforms, Paul proposed and developed three proof-of-concept (POC) systems, all produced with Clojure, ClojureScript and Datomic. The last POC rebuilt an existing system, providing a benchmark for comparison.

Code Metrics

In terms of project metrics, two developers designed and implemented the engine/runtime/tool/platform that was then used to rapidly prototype additional concepts in 3-4 weeks. Brand-new applications can be created in minutes or hours, and result in 10-50 lines—compared to the days/weeks/months and thousands of lines required by the old paradigm. To learn more about Paul's work with data-driven microservices, see his talk from Clojure/Conj 2014, Unlocking Data-driven Systems.   

Data Orientation Drives Antifragility

What about scaling? When I started moving from objects to functional programming, my big fear was that I'd be back in the days where changing a 'struct' in a header file broke code in totally different modules. Objects did afford us the luxury of hiding decisions and ignoring them. Of course, instead of coupling to a structure definition we coupled to a class definition, but at least parts of it could be made private. Wouldn't functional programming land us back in the days of limited program complexity due to data structure coupling?

Nothing exists in a vacuum. The data oriented, function style is becoming popular at the same time as microservice architectures. This is not a coincidence and it is not totally driven by the necessities of multicore programming. Rather, we have discovered that there is an upper bound on scaling a system up via object-oriented programming. Too many companies have created golden anchors out of their multimillion line code bases. We are uncovering new ways to structure applications that enforce even stronger encapsulation and decision-hiding than object-oriented programming. In doing so, we are getting back Alan Kay's original ideas: it's about the messages.

You can think about each microservice as being an autonomous actor–a black box. You can send it messages. It sends messages back or it sends messages to others. We are implementing these with functional programming, but that is invisible from outside the black box. We choose data orientation inside the box because it makes the code smaller and more disposable.

Data orientation unlocks the value of your data and is a means to gaining high leverage. You can think of high leverage as the difference between steering a bus and steering a sports car. The same small steering wheel turn gives you a much bigger change in direction with the sports car. When you’re working with high leverage, you don’t have to put as much investment in to get the same functionality or value out. Because your code is simpler and easier to create, it can be considered disposable. And with disposable code, you don’t feel the compulsion to keep it, like you would with the old paradigm boat anchor projects. It all adds up to this: data orientation drives antifragility, enabling you to change individual vectors, and your entire organization more swiftly.

Read all of Michael Nygard's The New Normal series here.  


Best of TIL Year One: Ruby

Here are some of the top Ruby posts from Today I Learned.

My goal with this series is to pause and highlight some of the top posts from the first year of Today I Learned. Today we'll look at Ruby, our third-most active channel.

Hashrocket invested early in Ruby, and it remains the lingua franca of our company. Though many of us enjoy hacking on JavaScript, Elixir, Go, Clojure, and other languages, Ruby is still a well-worn and trusty tool. We travel to Rails Conf and Ruby Conf each year, and host our own annual Ruby conference in St. Augustine. There's a cache at Hashrocket to an elegant line of Ruby, because it's a language we all know well.

Here are the top five most liked Ruby posts, in order, from the first year of Today I Learned.


Ruby String Mutability (Vinicius Negrisolo)

Until Ruby 3 we need to explicitly call the method freeze on literal strings, so they become immutable. And, if you have a lot of literal strings in a file, this will be very repetitive and verbose. In order to let our code cleaner there is a magic comment that can be added in the top of each file.

the magic:

# frozen_string_literal: true

And it is done, all literal string are frozen now :)


class Unfrozen
  def foo
class StringFrozen
  def foo
# frozen_string_literal: true
class ClassFrozen
  def foo

To test that:

require 'spec_helper'

describe 'Ruby String Mutability' do
  it 'validates string mutability' do
    expect( to be false
    expect( to be true
    expect( to be true
Randomized with seed 51265

Finished in 0.00179 seconds (files took 0.45396 seconds to load)
1 example, 0 failures


Ruby Retry- Where you been? (Micah Cooper)

For some reason, I never knew about ruby's retry keyword. The more you know...

def api_request
  TwitterWrapper.make_request # Throws a ServiceUnavailabe(506)- Server overloaded
 rescue ServiceUnavailable => error
    retries = retries.to_i + 1 # Increment a retry counter
    retries < 5 ? retry : raise(error) # run the method again until "retries is exceeded"
    # notice the local variable "retries" is persisted through retries

You could put a sleep in there if you wanted to wait a certain amount of time before retrying.

h/t Vinicius Negrisolo

Percent Notation (Josh Branchaud)

Ruby has many uses for the % character. One of the more obscure uses is as a notion for custom delimited strings. Use the percent notation with a non-alphanumeric character to surround a string.

&gt; %=Jurassic Park=
=&gt; "Jurassic Park"
&gt; % Ghostbusters 
=&gt; "Ghostbusters"

It even works with balanced characters

&gt; %(The Goonies)
=&gt; "The Goonies"

This is useful for defining a string that has both types of quotes

&gt; %[That'll be the "day"]
=&gt; "That'll be the \"day\""

It's also useful for creating horribly obfuscated code

&gt; %=what===%?what?
=&gt; true

h/t Josh Davey

Ruby array shortcuts - "&:" and "&method" (Vinicius Negrisolo)

Call a method on every items with &:

So this:

[:foo, :bar].each do |item|

Can be reduced to:

[:foo, :bar].each(&:to_s)

But, what if you want to call a method for each item in an array, and this item should be a parameter for this method?

Call a method with every items as a parameter with &method

So this:

[:foo, :bar].each do |item|

Can be reduced to:

[:foo, :bar].each(&method(:puts))

A high level view of RSpec tests (Chris Erin)

Test files in ruby/rspec can grow to gigantic soul crushing sizes, which makes it hard to really get a sense of what tests are in the file and where. This is troublesome when trying to determine a sensible place to add a new test to the already gigantic file.

To get a better sense of the structure of the file you can combine the dry-run and format options for readable, hierarchical documentation in a small amount of time.

$ rspec -fdoc --dry-run specs/my_massive_test_file_spec.rb


Thanks to Vinicius, Micah, Josh, and Chris for these posts.

Today I Learned had a spike in traffic near the beginning of the year, and these posts are mostly from that time. But there's a lot of great Ruby tips from earlier. See them all here:

Keep instantiating those objects, and learning every day.

This blog post is part three of a series; here's part one and two. Next, we will look at the top command line posts from year one.


Functional Geekery Episode 57 – Mark Seemann

In this episode I talk with Mark Seemann. We talk his introduction to functional programming and F#, common principles between functional programming and object oriented programming, Haskell, lessons learned, planting the seeds of functional programming, and much, much more.

Our Guest, Mark Seemann

@ploeh on Twitter
Mark blogs at


This episode is sponsored by project management tools for software teams. Visit to sign up for a free trial and a $50 credit. Clubhouse: dream, develop, deploy.


Curry On is taking place July 18th and 19th in Rome. Visit to find out more and to register.

ElixirConf is taking place August 31st through September 2nd in Orlando, Florida. Visit to register and find out more.

Full Stack Fest will be hold in Barcelona on September 5-9th. You can check out to find out more.

PWLConf 2016 is the first full-day Papers We Love conference, co-located with the preconference events at Strange Loop in Saint Louis, Missouri on September 15th. Keep an eye out for updates on

The Erlang User Conference is coming up in Stockholm, Sweden, the 6th through the 16th of September. Early Bird tickets are now available and get a 10% discount on the conference when you use the code: FunctionalGeekery10 when registering.

Destination Code, a new unconference starting in Utah, is having its inaugural event this December. Visit to find out more.

CodeMesh is taking place the 3rd and 4th of November with tutorials on the 2nd of November. Tickets are available now, but they are going fast. Visit to register and submit your talk.

If you have a conference related to functional programming, contact me, and I will be happy to announce it.


About Mark
How Mark got into software development
Real-World Functional Programming: With Examples in F# and C#
“My C# programming has changed fundamentally from being exposed to F#”
“[F#] felt like coming home”
Eric Evans’ Domain Driven Design
Robert C. Martin’s Clean Code
Command Query Separation from Bertrand Meyer in Object Oriented Software Construction
Having side effects separated from the rest of your code
“Functional programming is imminently testable”
Jessica Kerr on isolation in Functional Programming on Episode 8
DHH’s article on Test-induced design damage
Michael Feathers’ Working Effectively with Legacy Code and seams in code
“Am I writing good F# code?”
Learning Haskell
The struggle of introducing good abstractions
Overview of Functor Type Class and difference between F# and Haskell
Edwin Brady on designing with types on Episode 54
How F# influences Mark’s C#
Structural Equality
Interfaces with only one method as rough equivalent to a function
Porting F# to Haskell to determine if F# is “really good”
“How do I call my database inside my function?'”
Gerard Meszaros’ xUnit Test Patterns
Direct vs Indirect inputs and outputs
Mark’s post on the migration from F# to Haskell
On evangelizing F# and functional programming
Once people start being interested it becomes easy to introduce a small library in F#
Planting the seed of an idea of F# or functional programming
Curiosity of the lack of discriminated unions in C# or Java
Overview of Mark’s Pluralsight courses
Interest in Clojure to see difference in statically vs dynamically typed languages

As always, a giant Thank You goes to David Belcher for the logo design.


Multi language live snippets with the klipse plugin by @viebel

What is Klipse?

The klipse plugin is a javascript tag that transforms static code snippets of an html page to live and interactive snippets:

  1. Live: The code is executed in your browser
  2. Interactive: You can modify the code and it is evaluated as you type

The code evaluation is done in the browser: no server is involved at all!

Read more about the klipse plugin.

In this short article, we show live code snippets in different languages.

Modify the code in the snippets and enjoy the interactivity!



[1, 2, 3].map((x) => x + 1)


[1, 2, 3].map{|x| x + 1}


$name = "klipse";
echo "hello". " " . $name;


(map inc [1 2 3])


Immutant 2.1.5 Release

We just released Immutant 2.1.5. This release includes the following changes:

  • Support for deployment to the newly-released JBoss EAP 7
  • A fix to allow you to use XA, immutant.messaging/listen, and a remote context together
  • We no longer transitively depend on two different versions of jboss-logging
  • Our Undertow dependency has been updated to 1.3.23.Final (from 1.3.0.Beta9) to fix issues with HTTP/2 in Chrome (IMMUTANT-621)
  • Other updates to our transitive depenencies, including:
    • java.classpath 0.2.2 -> 0.2.3
    • potemkin 0.4.1 -> 0.4.3
    • tools.nrepl 0.2.7 -> 0.2.11

We're especially proud to announce full support for EAP7 on the day of its official release, expanding our supported deployment options to the following:

  • Standalone
  • JBoss EAP 6.4 and 7.0
  • WildFly 8, 9, and 10
  • Clojure 1.7, 1.8, and 1.9

Our comprehensive, automated integration test suite verifies all of these whenever a change to Immutant is committed.

What is Immutant?

Immutant is an integrated suite of Clojure libraries backed by Undertow for web, HornetQ for messaging, Infinispan for caching, Quartz for scheduling, and Narayana for transactions. Applications built with Immutant can optionally be deployed to a WildFly or JBoss EAP cluster for enhanced features. Its fundamental goal is to reduce the inherent incidental complexity in real world applications.

Get In Touch

As always, if you have any questions, issues, or other feedback about Immutant, you can always find us on #immutant on freenode or our mailing lists.

Issues resolved in 2.1.5


Immutant 2.1.4 Release

We just released Immutant 2.1.4. There are just a couple of small changes in this release, only one of which is notable: you can now provide a handler deal with any errors that occur when writing the ring response. For details, see the immutant.web/run docstring and the example in IMMUTANT-615.

What is Immutant?

Immutant is an integrated suite of Clojure libraries backed by Undertow for web, HornetQ for messaging, Infinispan for caching, Quartz for scheduling, and Narayana for transactions. Applications built with Immutant can optionally be deployed to a WildFly cluster for enhanced features. Its fundamental goal is to reduce the inherent incidental complexity in real world applications.

Get In Touch

As always, if you have any questions, issues, or other feedback about Immutant, you can always find us on #immutant on freenode or our mailing lists.

Issues resolved in 2.1.4

  • [IMMUTANT-613] - Add boot-immutant to WildFly guide
  • [IMMUTANT-614] - Using a dev war prints out a deprecation warning for app-relative
  • [IMMUTANT-615] - User can't catch errors that occur when writing the ring response
  • [IMMUTANT-616] - Allow adding extensions to undertow's WebSocket handshake handler


Copyright © 2009, Planet Clojure. No rights reserved.
Planet Clojure is maintained by Baishamapayan Ghose.
Clojure and the Clojure logo are Copyright © 2008-2009, Rich Hickey.
Theme by Brajeshwar.