Langohr 3.1.0 is released

TL;DR

Langohr is a small Clojure RabbitMQ client.

3.1.0 upgrades dependencies and includes one bug fix in Langohr itself.

Changes between Langohr 3.0.x and 3.1.0

RabbitMQ Java Client Upgrade

RabbitMQ Java client dependency has been updated to 3.4.4.

It includes an important binding recovery bug fix.

clj-http Upgrade

clj-http dependency has been updated to 1.0.1.

Cheshire Upgrade

Cheshire dependency has been updated to 5.4.0.

langohr.consumers/blocking-subscribe No Longer Fails

langohr.consumers/blocking-subscribe no longer fails with a function arity exception.

GH issue: #65.

Change Log

Langohr change log is available on GitHub.

Langohr is a ClojureWerkz Project

Langohr is part of the group of libraries known as ClojureWerkz, together with

  • Elastisch, a minimalistic well documented Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client built around CQL 3.0
  • Monger, a Clojure MongoDB client for a more civilized age
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Langohr, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About The Author

Michael on behalf of the ClojureWerkz Team

Permalink

The Paper Metaphor

Functional programs follow a simple rule: never write on the same paper twice. Imperative programs are free to define their own rules. Both have interesting consequences.

Read full post

Permalink

Lisp In Small Pieces (In Clojure)

This gist is chapter 3 of Lisp In Small Pieces - ported to Clojure. It was a fairly natural port, since the object system used in chapter 3 (not implemented until chapter 11) is easily simulated using Clojure's multimethods, and keyword heirarchies.

Here are some fun forms you can try to evaluate. Bonus points for being able to mentally follow what is going on with all the continuations flying around!

;; returns 3, since the throw to the first catch is interrupted ;; by another throw.
(catch 1
       (catch 2 (* 7
                   (throw 1 (throw 2 3)))))

;; proves that the cleanup form in the unwind protect 
;; is being run during a throw.
((lambda (a) (cons (catch 1
                          (unwind-protect
                           (throw 1 89)
                           (set! a 45)))
                   a))
 34)

;; proves that the return-from works, and that the cleanup form 
;; in the unwind-protect is being run.
((lambda (a) (cons (block 1 (unwind-protect
                             (return-from 1 2)
                             (set! a 89))
                          3)
                   a))
 34)

Permalink

Serving Custom JSON From Your Rails API With ActiveModel::Serializers

These days, there are so many different choices when it comes to serving data from an API. You can build it in Node with ExpressJS, in Go with Martini, Clojure with Compojure, and many more. But in many cases, you just want to bring something to market as fast as you can. For those times, I still reach for Ruby on Rails.

With Rails, you can spin up a function API server in a very short period of time. Rails is large. Perhaps you object that there's "too much magic". Have you ever checked out the rails-api gem? It lets you enjoy all the benefits of Rails without including unnecessary view-layer and asset-related code.

Rails-api is maintained by Carlos Antonio Da Silva, Santiago Pastorino, Rails Core team members, and all-around great Rubyist Steve Klabnik. While not busy working on Rails or the Rails API Gem, they found the time to put together the active_model_serializers gem to make it easier to format JSON responses when using Rails as an API server.

ActiveModel::Serializers (AMS) is a powerful alternative to jbuilder, rabl, and other Ruby templating solutions. It's easy to get started with, but when you want to serve data that quite doesn't match up with the way ActiveRecord (AR) structures things, it can be hard to figure out how to get it to do what you want.

In this post, we'll take a look at how to extend AMS to serve up custom data in the context of a Rails-based chat app.

Kicking It Off: Setting Up a Rails Server

Any two users in the system can have a continuous thread that goes back and forth. Let's imagine we are building a chat app, similar to Apple's Messages. People can sign up for the service, then chat with their friends.

Most of the presentation logic will happen in a client-side JavaScript app. For now, we're only concerned with accepting and returning raw data, and we've decided to use a Rails server to build it. To get started, we'll run a rails new, but since we're using the rails-api gem, we'll need to make sure we have it installed first, with:

gem install rails-api

Once that's done, we'll run the following (familiar) command to start the project:

rails-api new mensajes --database=postgresql

Then cd into the directory and setup the database with:

rake db:create

Creating the Models

We'll need a couple of models: User and Message.

The workflow to create them should be fairly familiar:

rails g scaffold user username:string
rails g scaffold message sender_id:integer recipient_id:integer body:text

Open up the migrations, and set everything to null: false, then run rake db:migrate.

We'll also need to set up the relationships. Be sure to test these relationships (I would suggest using the shoulda gem to make it easy on yourself.

class User < ActiveRecord::Base
  has_many :sent_messages, class_name: "Message", foreign_key: "sender_id"
  has_many :received_messages, class_name: "Message", foreign_key: "recipient_id"
end
class Message < ActiveRecord::Base
  belongs_to :recipient, class_name: "User", inverse_of: :received_messages
  belongs_to :sender, class_name: "User", inverse_of: :sent_messages
end

Serving the Messages

Let's send some messages! Imagine for a minute that you've already set up some kind of token-based authentication system, and you have some way of getting ahold of the user that is making requests to your API.

We can open up the MessagesController, and since we used a scaffold, we should already be able to view all the messages. Let's scope that to the current user.

First, we write a convenience method to get all the sent and received messages for a user: class User < ActiveRecord::Base ... def messages Message.where("sender_id = ? OR recipient_id = ?", self.id, self.id) end end

Then, we rework the MessagesController to work the way we want it to:

class MessagesController < ApplicationController
  def index
    @messages = current_user.messages
    render json: @messages
  end
end

Assuming that we have created a couple of sent and received messages for the current_user, we should be able to take a look at http://localhost:3000/messages and see some raw JSON that looks like this:

[  
   {  
      "sender_id":1,
      "id":1,
      "recipient_id":2,
      "body":"YOLO",
      "created_at":"2015-02-03T21:05:12.908Z",
      "updated_at":"2015-02-03T21:05:12.908Z"
   },
   {  
      "recipient_id":1,
      "id":2,
      "sender_id":2,
      "body":"Hello, world!",
      "created_at":"2015-02-03T21:05:51.309Z",
      "updated_at":"2015-02-03T21:05:51.309Z"
   }
]

It's kind of ugly. It would be nice if we could remove the timestamps and IDs.

This is where AMS comes in.

Adding ActiveModel::Serializers

Once we add AMS to our project, it should be easy to get a much prettier JSON format back from our MessagesController.

To get AMS, add it to the Gemfile with:

gem "active_model_serializers", github: "rails-api/active_model_serializers"

Then bundle install. Note that I'm using a the edge version of AMS here because it supports belongs_to and other features. See the github project README for some information about maintenance and why you might want to use an older version.

Now we can easily set up a serializer with rails g serializer message.

Let's take a look at what this generated for us.

In app/serializers/message_serializer.rb, we find this code:

class MessageSerializer < ActiveModel::Serializer
  attributes :id
end

Whichever attributes we specify (as a list of symbols) will be returned in the JSON response. Let's skip id, and instead return the sender_id, recipient_id, and body:

class MessageSerializer < ActiveModel::Serializer
  attributes :sender_id, :recipient_id, :body
end

Now when we visit /messages, we get this slightly cleaner JSON:

{  
   "messages":[  
      {  
         "sender_id":1,
         "recipient_id":2,
         "body":"YOLO"
      },
      {  
         "sender_id":2,
         "recipient_id":1,
         "body":"Hello, world!"
      }
   ]
}

Cleaning Up the Format

It sure would be nice if we could get more information about the other user, like their username, so that we could display it in the messaging UI on the client-side. That's easy enough, we just change the MessageSerializer to use AR objects as attributes for the sender and recipient, instead of ids.

class MessageSerializer < ActiveModel::Serializer
  attributes :sender, :recipient, :body
end

Now we can see more about the Sender and Recipient:

{  
   "messages":[  
      {  
         "sender":{  
            "id":1,
            "username":"Ben",
            "created_at":"2015-02-03T21:04:09.220Z",
            "updated_at":"2015-02-03T21:04:09.220Z"
         },
         "recipient":{  
            "id":2,
            "username":"David",
            "created_at":"2015-02-03T21:04:45.948Z",
            "updated_at":"2015-02-03T21:04:45.948Z"
         },
         "body":"YOLO"
      },
      {  
         "sender":{  
            "id":2,
            "username":"David",
            "created_at":"2015-02-03T21:04:45.948Z",
            "updated_at":"2015-02-03T21:04:45.948Z"
         },
         "recipient":{  
            "id":1,
            "username":"Ben",
            "created_at":"2015-02-03T21:04:09.220Z",
            "updated_at":"2015-02-03T21:04:09.220Z"
         },
         "body":"Hello, world!"
      }
   ]
}

Actually, that might be too much.

Let's clean up how User objects are serialized by generating a User serializer with rails g serializer user. We'll set it up to just return the username.

class UserSerializer < ActiveModel::Serializer
  attributes :username
end

In the MessageSerializer, we'll use belongs_to to have AMS format our sender and recipient using the UserSerializer:

class MessageSerializer < ActiveModel::Serializer
  attributes :body
  belongs_to :sender
  belongs_to :recipient
end

If we take a look at /messages, we now see:

[  
   {  
      "recipient":{  
         "username":"David"
      },
      "body":"YOLO",
      "sender":{  
         "username":"Ben"
      }
   },
   {  
      "recipient":{  
         "username":"Ben"
      },
      "body":"Hello, world!",
      "sender":{  
         "username":"David"
      }
   }
]

Things are really starting to come together!

Conversations

Although we can view all of a user's messages using the index controller action, or a specific message at the show action, there's something important to the business logic of our app that we can't do. We can't view all of the messages sent between two users. We need some concept of a conversation.

When thinking about creating a conversation, we have to ask, does this model need to be stored in the database? I think the answer is no. We already have messages that know which users they belong to. All we really need is a way to get back all the messages between two users from one endpoint.

We can use a Plain Old Ruby Object (PORO) to create this concept of a conversation model. We will not inherit from ActiveRecord::Base in this case.

Since we already know about the current_user, we really only need it to keep track of the other user. We'll call her the participant.

# app/models/conversation.rb
class Conversation
  attr_reader :participant, :messages

  def initialize(attributes)
    @participant = attributes[:participant]
    @messages = attributes[:messages]
  end
end

We'll want to be able to serve up these conversations, so we'll need a ConversationsController. We want to get all of the conversations for a given user, so we'll add a class-level method to the Conversation model to find them and return them in this format:

[  
   {  
      "messages":[  
         {  
            "body":"YOLO",
            "recipient":{  
               "username":"David"
            },
            "sender":{  
               "username":"Ben"
            }
         },
         {  
            "body":"Hello, world!",
            "recipient":{  
               "username":"Ben"
            },
            "sender":{  
               "username":"David"
            }
         }
      ],
      "participant":{  
         "username":"David"
      }
   }
]

To make this work, we'll run a group_by on the user's messages, grouping by the other user's ID. We'll then map the resulting hash into a collection of Conversation objects, passing in the other user and the list of messages.

class Conversation
  ...
  def self.for_user(user)
    user.messages.group_by { |message|
      if message.sender == user
        message.recipient_id
      else
        message.sender_id
      end
    }.map do |user_id, messages|
      Conversation.new({
        participant: User.find(user_id),
        messages: messages
      })
    end
  end
end

If we run this in the Rails Console, it seems to be working.

>Conversation.for_user(User.first)
...
=> [#<Conversation:0x007fbd6e5b9428 @participant=#<User id: 2, username: "David", created_at: "2015-02-03 21:04:45", updated_at: "2015-02-03 21:04:45">, @messages=[#<Message id: 1, sender_id: 1, recipient_id: 2, body: "YOLO", created_at: "2015-02-03 21:05:12", updated_at: "2015-02-03 21:05:12">, #<Message id: 2, sender_id: 2, recipient_id: 1, body: "Hello, world!", created_at: "2015-02-03 21:05:51", updated_at: "2015-02-03 21:05:51">]>]

Great! We'll just call this method in our ConversationsController and everything will be great!

First, we'll define the route in config/routes.rb:

Rails.application.routes.draw do
  ...
  resources :conversations, only: [:index]
end

Then, we'll write the controller action.

# app/controllers/conversations_controller.rb

class ConversationsController < ApplicationController
  def index
    conversations = Conversation.for_user(current_user)
    render json: conversations
  end
end

Visiting /conversations, we should see a list of all the conversations for the current user.

Whoops! Something’s wrong. But what is it?

Serializing Plain Old Ruby Objects

When we visit that route, we get an error: undefined method `new' for nil:NilClass. It's coming from this line in the controller:

render json: conversations

It looks like the error is coming from the fact that we don't have a serializer. Let's make one with rails g serializer conversation. We'll edit it to return its attributes, participant and message.

class ConversationSerializer < ActiveModel::Serializer
  attributes :participant, :messages
end

Now when we try, we get another error, coming from the same line of the controller:

undefined method 'read_attribute_for_serialization' for #<Conversation:0x007ffc9c1bed10>

Digging around in the source code for ActiveModel::Serializers, I couldn't find where that method was defined. So I took a look at ActiveModel itself, and found it here. It turns out that it's just an alias for send!

We can add that into our PORO easily enough:

class Conversation
  alias :read_attribute_for_serialization :send
  ...
end

Or, we could include ActiveModel::Serialization which is where our AR-backed objects got it.

Now when we take a look at /conversations, we get:

[  
   {  
      "participant":{  
         "id":2,
         "username":"David",
         "created_at":"2015-02-03T21:04:45.948Z",
         "updated_at":"2015-02-03T21:04:45.948Z"
      },
      "messages":[  
         {  
            "sender_id":1,
            "recipient_id":2,
            "id":1,
            "body":"YOLO",
            "created_at":"2015-02-03T21:05:12.908Z",
            "updated_at":"2015-02-03T21:05:12.908Z"
         },
         {  
            "sender_id":2,
            "id":2,
            "recipient_id":1,
            "body":"Hello, world!",
            "created_at":"2015-02-03T21:05:51.309Z",
            "updated_at":"2015-02-03T21:05:51.309Z"
         }
      ]
   }
]

Whoops! Not quite right.

But the problem is similar to the one we had before in the MessageSerializer. Maybe the same approach will work.

We'll change the attributes to AR relationships.

class ConversationSerializer < ActiveModel::Serializer
  has_many :messages, class_name: "Message"
  belongs_to :participant, class_name: "User"
end

Almost! Now /conversations returns:

[  
   {  
      "messages":[  
         {  
            "body":"YOLO"
         },
         {  
            "body":"Hello, world!"
         }
      ],
      "participant":{  
         "username":"David"
      }
   }
]

We can't see who the sender of each message was! AMS isn't using the UserSerializer for the message sender and recipient, because we're not using an AR object.

A little source code spelunking points the way to a fix.

class MessageSerializer < ActiveModel::Serializer
  attributes :body, :recipient, :sender

  def sender
    UserSerializer.new(object.sender).attributes
  end

  def recipient
    UserSerializer.new(object.recipient).attributes
  end
end

Now /conversations gives us what we want:

[  
   {  
      "messages":[  
         {  
            "body":"YOLO",
            "recipient":{  
               "username":"David"
            },
            "sender":{  
               "username":"Ben"
            }
         },
         {  
            "body":"Hello, world!",
            "recipient":{  
               "username":"Ben"
            },
            "sender":{  
               "username":"David"
            }
         }
      ],
      "participant":{  
         "username":"David"
      }
   }
]

And /messages still works as well! Woo hoo!

Wrapping Up

The ActiveModel::Serializers gem claims to bring "convention over configuration to your JSON generation." And it does a great job of it. But when you need to massage the data, things can get a little bit hairy.

Hopefully some of the tricks we've covered will help you serve JSON from your Rails API with the structure you want. For this, and virtually any other problem caused by "the magic" getting in the way, I suggest digging through the source code.

At the end of the day, ARS is an excellent choice for getting your JSON API off the ground with a minimum of fuss. Good luck!

P.S. Have a different approach? Prefer rabl or jbuilder? Did I leave something out? Leave us a comment below!

Permalink

GitHub Streaking for Fun and Profit

At the time of writing, I'm on day 68 of my longest GitHub streak yet. It's been the most productive 2 months ever, and I intend to keep the streak going for as long as possible. My secret weapon? The concept of the GitHub streak itself.

Many people have blogged about this before, and for good reason. I'm convinced that the "Seinfeld Streak" is one of the most powerful techniques you can utilize to increase your productivity and develop good habits. The premise is simple: do the thing you want to do on a daily basis, and keep track of your streak. Whatever you do, do not break the chain. It may seem like kind of a silly idea on the surface, but in practice, I've found it to be incredibly motivating. GitHub is already keeping track of my streak, so my goal is just to keep that number increasing every day. If I miss a day, my streak will go back down to 0 and I'll lose all of my progress. That knowledge is all the motivation I need to push code every day and maintain my streak.

The nice thing is that the rules for what counts as a contribution are fairly liberal. Essentially, any commit you make to the default/master branch of a repo will count towards your streak. Creating an issue or a pull request also counts. I think this is a nice balance between requiring quality activity (not just, say, writing some bad code in an experimental fork which you will later delete) and not being so demanding as to be intimidating. The result, should you choose to become a GitHub streaker, is a low-stress habit that keeps you programming and thinking about programming, and maybe will even get you to finish some projects you didn't think you had time for.

The Benefits

It forces you to make time to code

Like any good habit, working on open-source projects is something we often don't feel like we have time for. But in reality, we have plenty of free time -- it's just that we often end up spending it vegging out in front of the TV, or spending inordinate amounts of time doing nothing in particular on the internet. I've found that all it really takes to be successful in following these habits is having a self-imposed requirement to do them. I have to push some code in order to keep my streak going, and so without even realizing it, I've started making working on code a daily priority.

You'll manage your time better

The most surprising thing about my experience so far as a GitHub streaker is that I've actually found myself becoming more of a morning person. Whereas before, my tendency would be to sleep in until an hour or so before I need to be at work, maintaining a streak of GitHub activity has made me realize the value of the morning hours before work. You may have heard that the creative mind works best first thing in the morning -- I've found this to be true. Sometimes an obvious solution to a problem will just come to me, seemingly out of nowhere, if I work on it right after waking up. The result of being awake earlier is that I get more things done in the morning, giving me more free time in the afternoon and evening.

You'll get better at programming

This one is a no-brainer. The more code you write, and the more you challenge yourself to work on a variety of different projects, the more you'll expand your horizons and the better you'll get at writing quality code.

Additionally, having all of your code "out in the open" on GitHub can serve to motivate you to write code that is clearer and easier for other people to read and understand. I think this is the essence of being a good programmer.

Open-source is awesome

When you have more time in your day dedicated to writing code, you may find yourself branching out and making contributions to others' repos. That's one of the beautiful things about GitHub, and it's sadly neglected when all you have time for (or so you think) is working on your own projects. You'll find that being an open-source contributor really doesn't take as much time and effort as you might think. If you're ever using someone else's library and you find yourself thinking, "this library is great, but I wish it had feature X," and you start coding a work-around in your project to implement feature X on top of said library, stop and consider whether it might make more sense to actually contribute feature X to the library. If you think about it, it really doesn't take much more time than writing the feature into your project, so you may as well go ahead and fork the library and make a pull request!

Another nice aspect of open-source software is that project development is contagious. Open-source software developers are constantly making cool new things, creating new tools that other developers can leverage to speed up development on their own projects and libraries, and the cycle continues. In this way, OSS developers can empower and inspire each other to be productive and Get Shit Done™.

Tips & Tricks

Take advantage of the Issues system.

As I mentioned, creating a new issue on a project counts toward your GitHub activity for the day. This can be an easy way to get your activity in for the day if you're crunched for time. Maybe you're working on a new feature, but it still needs some work and the tests aren't quite passing yet. If you don't think you'll have time to finish it that day, you can do the next best thing, which is to spec it out in the form of a GitHub issue. This may seem like a cop-out to some, but it can actually be very helpful. As you write out your ideas for this feature, you might have a revelation, get some new ideas, or at least come up with a solid game plan for implementing the feature.

Whether you're attempting a GitHub streak or not, I think the Issues system on GitHub is a fantastic tool for project development. It has obvious benefits for collaboration on a project, in that it allows collaborators to articulate their thoughts on specific issues and discuss the direction of the project. But I've even found it useful for projects that I'm working on by myself. GitHub issues often serve as a way for me to hold onto thoughts about how to fix bugs or ideas for features I eventually want to implement. If I didn't have some method of documenting this information for my own later use, I would probably lose track of at least some of it by the time I end up working on the project again, which could be days, weeks or months later in some cases.

Open-source your hobbies

The more you browse other people's GitHub repos, the more examples you'll find of novel things to put on GitHub. For the purpose of maintaining your streak, making repos for things works in your favor, even if they're for things you wouldn't have otherwise thought deserved a repo.

I've seen many people store their configuration dotfiles in a repo, which is both a good way to synchronize your settings across machines and a way to share your favorite configurations with others. There are endless ways to customize certain pieces of software.

Are you working your way through a programming book? Learning a new language? Learning to do a new thing, like building a web app in Clojure? Make a repo to document your progress! You'll probably end up paying more attention to the code you write, and you may even inspire other people to learn what you're learning.

If you're ever looking for new projects, a good standby is to take a library that interests you, but lacks support in a given language, and write your own language-specific library. As an example, one of the projects I'm working on involves interacting with mpd with Clojure. A quick google search showed me there was a Java library for this called javampd, and someone had started writing a library for more idiomatic use of mpd in Clojure by wrapping javampd, but it needed some fleshing out. So, it turned into a perfect opportunity for me to contribute to OSS.

Speaking of Clojure, Boot has been all the rage lately. Boot's concept of tasks opens up an exciting new world of possibilities to give you more control over your development workflow. There is already a wealth of useful community-contributed Boot tasks, but there is always room for more, and this is of course a great opportunity to be an open-source contributor. If there is anything you can think of that you do all the time when developing software, that can be automated, and that there isn't already a Boot task for, well, maybe you should try your hand at writing one!

Start your streak today

Hopefully I've convinced you of the benefits of letting your GitHub streak motivate you to write code every day. Have fun, branch out, and remember - whatever you do, don't break the chain!

Permalink

My Clojure Toolchain: Vim

Oh, hi. You're back. Well, since you apparently didn't get sick of me talking about Clojure tools last time, let's keep going.

Vim is my terminal-based text editor of choice. It's highly configurable, but for me, it looks like this:

Terminal

If you want to get into what's going on there - my .vimrc file isn't particularly organized, but if you're curious it looks like this. I use Solarized as my color scheme.

Why Use Vim?

This is one of those subjects that has inspired religious wars for decades. The short version goes like this: if you're a systems engineer, at some point you're going to need to familiarize a terminal-based text editor, and it should be one that you can expect to find on any reasonable UNIX system. Often, this boils down to a choice between Emacs and Vim (those being the two most mature and widely distributed such programs).

My reasons for using Vim are simple: several years ago, when the universe was still forming in the white heat of the big bang, I had the choice to learn Emacs or to learn Vim, and I chose to learn Vim.

...there isn't anything more to that story.

Honestly, at this point I'm familiar with Vim's tricks and idiosyncrasies, and just don't feel inclined to learn a new editor. There's no denying that Emacs has an inherent and [literally] built-in advantage when it comes to Lisps, but the best tool is often the one you know.

Vim Plugins

The world of Vim plugins is both huge and awesome. In addition to the Clojure-specific plugins listed below, I use vim-airline, Syntastic, and NERDTree, among others.

You didn't come here for me to talk about Vim in general, though, so let's get down to brass tacks: Vim plugins for Clojure.

vim-fireplace

Fireplace is the killer plugin for Vim and Clojure. It starts what @tpope calls a "quasi-REPL" that can be used to connect to a running nREPL server. By default, Leiningen will write a .nrepl-port file in the project's root that contains the integer port that the nREPL server is running on. When you open a Clojure file in Vim, Fireplace reads the port from the .nrepl-port file and opens a connection as a nREPL client.

You can also manually connect to a REPL server from Vim with the :Connect command, which is handy if you need to connect to a REPL that wasn't initialized from the current project directory.

If for some reason you don't have a nREPL server started (either through Leiningen or the application itself), there's also vim-leiningen which will shell out to Java to initialize one for you based on what the plugin can infer of your classpath. However, this tends to be a bit on the slow side, and in general it's much faster to just have an nREPL server already running in the background for you to connect to.

I use the fireplace REPL for a few major things:

  • code traversal
  • grabbing docstrings
  • running tests
  • hot-reloading the file I'm editing into the JVM

Some of these - in particular, docstrings and tests - are the sorts of things I'd be doing in a REPL anyways. The others are less so, but are hugely valuable for a code editor to have.

Code traversal

Let's start with code traversal - entering gf (goto file) when the cursor is over a namespace will take you to the namespace file, which is particularly great when you're wondering how the hell one of your dependencies works. Otherwise, you'd have to dig up the jar on your classpath and navigate its contents (or worse, look at the code on GitHub, which would involve - gasp! - leaving the terminal). Once within another namespace, hitting CTRL+w backs you out of the namespace into the original file.

Docstrings

I'm of the opinion that docstrings (and documentation at large) are underrated. Since I'm essentially an idiot at a typewriter, I tend to look up function documentation frequently.

When I'm at the REPL, this means a lot of (doc x). Fireplace gives me the ability to do that with :Doc x, and provides an even better shortcut by setting K as a hotkey that looks up the docstring for the symbol under the cursor.

Running tests

If you're in a test namespace, you can use the :RunTests command to kick off a conventional (clojure.test/run-tests), with the results loaded into a quickfix file

I also have a little Vim function (courtesy of my friend David Lowe) for running the test form under the current cursor. All this power and more can be yours for the low, low price of adding the following to your .vimrc (or wherever you store your Vim functions)!

function! TestToplevel() abort  
    "Eval the toplevel clojure form (a deftest) and then test-var the result."
    normal! ^
    let line1 = searchpair('(','',')', 'bcrn', g:fireplace#skip)
    let line2 = searchpair('(','',')', 'rn', g:fireplace#skip)
    let expr = join(getline(line1, line2), "\n")
    let var = fireplace#session_eval(expr)
    let result = fireplace#echo_session_eval("(clojure.test/test-var " . var . ")")
    return result
endfunction  
au Filetype clojure nmap <c-c><c-t> :call TestToplevel()<cr>  
Hot-reloading code into the JVM

This is, as far as I am concerned, the most important of Fireplace's features, and one I use pathologically. Using the :Require command is the equivalent of entering (require ... :reload) for the namespace in the current buffer, and I find myself doing this so often that I have it hotkeyed in my .vimrc as follows:

au Filetype clojure nmap <c-c><c-k> :Require<cr>  

My development flow looks something like this:

  1. Within Vim, make a few changes, write a new function, etc. Reload the changes into the current JVM with CTRL + C + CTRL + K.
  2. Switch tabs to a REPL, where I interactively play with and test my changes. This is done quickly by cycling through iTerm windows; ⌥ + ↑ or ⌥ + ↓ for windows in my current tab, and ⌥ + ← or ⌥ + → to change between tabs.
  3. Switch tabs back to Vim, rinse, repeat.
  4. Every half hour or so, run some tests. You have been writing tests, haven't you? ;)

When one is just starting out on a project and/or building very small and composable functions, the REPL alone can be a sufficient development environment. However, as the size of the codebase grows, I've found it easier to iteratively build functions by working on them in their target namespace within my editor, where I can more easily visualize and maintain context for what I'm working on. Fireplace is an incredible tool for supporting such a workflow

paredit.vim

Paredit.vim is another absolutely critical plugin to have for the Vim Clojure developer's toolbox. A component of the larger slimv ("Slime for Vim"), Paredit attempts to maintain the balanced state of matched characters for parenthesis, brackets, double quotation marks, etc.

If that were all it did, however, it would only be passingly useful. Its true value lies in its support for what Emacs users refer to as "Slurpage" and "Barfage" - the ability to, with a keystroke or two, move existing arguments into or out of a given form.

For instance, let's say I have the following in my editor:

(println (+ 1 1) 1)

What I really want, however, is to have that third one inside the form doing the addition. Well, with Paredit.vim, I can do that easily with two keystrokes, <Leader> >:

Buh-whaaaaa? So spice! I have my <Leader> mapped to ,, so for me the keys are right next to each other , >. This is really handy because Paredit doesn't naively push parenthesis around simple words, but rather around lisp forms. As a result, if I were to try to do the same command a second time, it wouldn't have any effect, because the inner parenthesis cannot logically be pushed outside of its containing form.

In addition to that, Paredit is great for wrapping forms in different wrappers, which is handy for when you've written something that needs to be refactored into a function, or needs let bindings added at some point.

Extra Credit: If Paredit is a part of slimv, why not just use Slimv? Great question, reader! To be totally honest, I don't have the best answer, and in fact, slimv might be great for you. However:

  1. It comes with its own REPL, and I think the current consensus among Vim + Clojure nerds that the Fireplace REPL is better.
  2. Paredit.vim is pure vimscript, and is extremely lightweight. slimv is much larger, and is all over the place: some common lisp, some Clojure, some Scheme, some Python, some VimL.

Ultimately, I prefer simplicity, and at this point I've been working in Vim long enough that I really trust Tim Pope's taste over most other plugin developers. But hey, you do you.

vim-surround

Next in the list of extremely useful functions for dealing with parenthesis is another Tim Pope plugin, vim-surround. This one probably deserves a place in your list of plugins whether you're working in Clojure or not, especially for when it comes to working with strings. What I find it most useful for, though, is for getting rid of stuff. As the good lord Paredit gives, vim-surround taketh away.

For example, check this out: ds( ("delete" "surrounding" "parens"):

Manually wrangling parentheses and other surrounding markers is a huge pain in the neck. Paredit.vim and vim-surround give you a large selection of key bindings to make working with such enclosures fast and easy.

vim-eastwood

You know I have a habit of hyping my own plugins, right? Well, if not, you do now! In my last post on Leiningen, I talked about Eastwood, the Clojure lint tool. vim-eastwood is a Vim plugin for Eastwood bindings that sits on top of Syntastic.

It requires you to have Eastwood on the Clojure classpath (i.e. preferably in your ~/.lein/profiles.clj) and to have a running nREPL server that you've connected to with Fireplace. After that, it feeds quickfix info on your current file to Syntastic, which generates handy markers in the left gutter and shows lint messages at the bottom of the screen when you move your cursor over the area in question:

vim-cljfmt

Continuing down the road of shameless self-promotion is another of my Vim Clojure plugins, which provides convenient bindings for cljfmt, the Clojure formatting tool. vim-cljfmt allows you to format the contents of the current Vim buffer through the :Cljfmt command, which by default is run every time you write the buffer to a file, much like how gofmt works.

Observe:

Now, isn't that nice?

Honorable Mentions

It would be remiss of me not to mention vim-clojure-static and rainbow parentheses; both are widely cited as being critical plugins for the Clojure developer working in Vim.

The truth is that I don't give much thought to vim-clojure-static since it's been shipping with Vim ever since 7.3.803, which was released over a year ago. As for rainbow parentheses - you know, I can see the value, but ever since installing Paredit.vim I haven't really felt particularly confused about what depth of nested parentheses I was working in. Personal preference, perhaps - if it works for you, I wish you all the best in using it.

This isn't a plugin, but it still deserves a shoutout - the hotkey, %, lets you find the starting/terminating parenthesis/bracket/brace for the one you've currently got your cursor on top of:

Conclusion

Anybody who has had the questionable privilege of having worked with me knows that I am peculiarly fanatical about tooling. I'm easily frustrated by poor tools, and I suffer from the engineer's afflication of always searching for a more perfect workflow.

One of the things I like about Vim is that it doesn't attempt to constrain me. If I want a new feature, I can add it - in a pretty wide range of languages - and I can rely on the editor's rich plugin ecosystem to provide painless ways to bind that functionality into the program.

Admittedly, writing plugins in VimScript isn't as lovely as writing everything in Clojure, but now that I've written two plugins in it I can't say that it's the worst language, either. It's just one that needs some better documentation and introductory material, which smarter people than I are already working on.

People tend to be fanatical about their editors, and so I don't anticipate anybody switching to Vim on basis of what I've covered here. However, for those of you already using Vim, I hope that this discussion of my workflow has been helpful. And for those of you who are curious about what the world of Vim is like, I hope this post shows that choosing Emacs for Clojure doesn't have to be a foregone conclusion.

Discuss this post on Hacker News or on Twitter (@venantius)

Thanks to Keith Ballinger (@keithba), Bill Cauchois (@wcauchois) and Harry Wolff (@hswolff) for reading drafts of this post.

Permalink

Senior Software Engineer at McGraw-Hill Education (Full-time)

This Senior Software Engineer position is with the new LearnSmart team at McGraw-Hill Education's new and growing Research & Development center in Boston's Innovation District.

We make software that helps college students study smarter, earn better grades, and retain more knowledge.

The LearnSmart adaptive engine powers the products in our LearnSmart Advantage suite — LearnSmart, SmartBook, LearnSmart Achieve, LearnSmart Prep, and LearnSmart Labs. These products provide a personalized learning path that continuously adapts course content based on a student’s current knowledge and confidence level.

On our team, you'll get to:

  • Move textbooks and learning into the digital era
  • Create software used by millions of students
  • Advance the state of the art in adaptive learning technology
  • Make a real difference in education

Our team's products are built with Flow, a functional language in the ML family. Flow lets us write code once and deliver it to students on multiple platforms and device types. Other languages in our development ecosystem include especially JavaScript, but also C++, SWF (Flash), and Haxe.

If you're interested in functional languages like Scala, Swift, Erlang, Clojure, F#, Lisp, Haskell, and OCaml, then you'll enjoy learning Flow. We don't require that you have previous experience with functional programming, only enthusiasm for learning it. But if you have do some experience with functional languages, so much the better! (On-the-job experience is best, but coursework, personal projects, and open-source contributions count too.)

We require only that you:

  • Have a solid grasp of CS fundamentals (languages, algorithms, and data structures)
  • Be comfortable moving between multiple programming languages
  • Be comfortable with modern software practices: version control (Git), test-driven development, continuous integration, Agile

Get information on how to apply for this position.

Permalink

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.