Philipp Meier - Software Developer

Abstracting the pain away

Homoiconicity Brings Pretty Graphs to Liberator

| Comments

homoiconic - Same representation of code and data, from homo meaning the same and icon meaning representation

DougMcIlroy & C.S.Peirce 1960 PeterDeutsch & CalvinMooers 1965 AlanKay 1969, C2-Wiki…

TL;DR - liberator source -> http flow chart in graphviz dot -> svg/png -> awesome

One of the key features of LISP is that it is homoiconic which, one could say, enables creative use of the source. The most prominent example are macros. Second, the generation of documentation from the the source is common practice even in heteroiconic languages but homoiconicity certainly makes it a lot easier. In this post I like to present a more exotic application: automatic generation of flow charts.

The liberator HTTP library provides a declarative way to implement HTTP resources conforming to the HTTP RFC. This is not as simple as it sounds, actually, RFC2616 is a large and complected piece of network engineering. To tame the beast liberator implements a decision graph containing a lot decision function callbacks which a developer can fill in or rely on a default implementation.

Based on this information the program flow takes a certain route and finally arrives at a handler which is responsible to build the actual HTTP response. The response will be based on the dervied status code, negotiated representation parameters as language and media type and so on.

For a more advanced use case consider a PUT a resource with a If-Not-Modified-Since-Header which returns a 302 see other. And there is more: content negotiation, conditional requests, checking for existance… The exact reason why a certain outcome was produced can be tricky to understand. This was the motivation to build a flow chart of the decision process, a feature that Erlang’s webmachine provides too. Webmachine actually was my inspiration to start what used to be called “compojure-rest” and now is liberator. You can find the flow chart for webmachine here.

And this is how it correlates with clojure’s homoiconicity. In the liberator code every decision is defined using a macro (defdecision name test then else) where “then” and “else” are names of other decisions. This actually looks like this:

We can then use a reader to read the source file that contains all the decisions (and actions, and handlers) into a list of lists and convert it into a Graphviz file:

Central idea is to “(read pr)” until no more expressions are available. Then map every expression to a string snippet which encodes one edge of the graph. To make this happen, to-graph looks for the two well known expressions (defdecision name then else) and (defaction name then) and convert them to an edge definition and some formatting.

The current implementation is more complete and formats “decisions”, “actions” and “handlers” differently. You can find it in the liberator source repository in test/doc.clj. For the current revision It produces this dot file (cut down to a reasonable size):

A rendered version of the graph looks like this:

You can access it in full size as png, svg and dot.

Variations Over Clojure Conditionals

| Comments

In clojure there is always more then one to do it. Here are some variations on conditionals. All five implementations use different ways to conditionally execute code and all satisfy the tests given in test-conditional.

Do you know more variation on this theme? Let me know in the comments!

Run Clojure Web Apps on Red Hat’s Openshift

| Comments

The other day I was toying around with RedHat’s PaaS openshift. Openshift has a free developer preview but here is currently no support for running leiningen or clojure apps. However, you can use the Do-It-Yourself application type and add the following as hooks to run leiningen yourself. The repository directory and home dir must be set because the home dir and working dir are read only. Leiningen or the maven libs seem to ignore $HOME, so I used -Duser.home to force the repository to another location.

I tested it with a dummy ring web application that runs with ring-jetty-adapter and binds to to $OPENSHIFT_INTERNAL_IP:$OPENSHIFT_INTERNAL_PORT

Another option is to use the available JBossAS-7 cartridge and deploy a .war-file. I failed to build an uberwar with the lein ring plugin, but this should be a perfectly valid option, too.