Bathroom Reading Material

Los Angeles

| Comments

When I last wrote about my life I had just flown out to Los Angeles for a week to get the lay of the land and spend some time at Geni, the company I was interning with. I was trying to decide if I should move out and work there full time, and by the end of that week I knew that that I had to. I’ve now been living in Los Angeles six months, and this is the story of how I got here.

Recap

I started using Clojure when I was very young. I was 15-16 and I did not have a whole lot of experience with programming. My background prior to that was Haskell, where I had some some trivial projects and swallowed up the most fundamental concepts I needed to get going. I started doing more significant and less trivial projects in Clojure, and began to build a bit of a portfolio with things like lazybot and tryclojure.

By nothing more than chance alone, I met two people who both changed my life. They would become two of my very best friends as well as coworkers. They saw potential in me (frequently more than I saw in myself) and eventually got me an internship at Geni. They jump-started my career at 17 years old. These guys were Justin Balthrop and Lance Bradley.

Long story short, I interned at Geni for nearly two years. Along the way I met Alan Malloy (amalloy) and we quickly became friends. It came to pass that he too ended up employed at Geni!

The Lows

Towards the end of 2012, we all decided it was time that I came and worked for Geni full time and in person. This meant I had to leave everything I knew behind and move across the country to Los Angeles. I’m from a small town in Alabama. Los Angeles was exciting, but entirely unfathomable to me. Nonetheless, I made the decision to do it because it was the best possible thing I could do, and I don’t regret it one bit.

On February 3rd, 2013, the day after my 19th birthday, I stepped onto a plane with a laptop, a small carry on bag full of clothes, and my das keyboard. These are the only things I had in the world from then on out.

Here’s the thing, guys. Most of you were inevitably in school for much of your life growing up. You left every morning, came back every night, maybe got angry at your parents for not letting you hang out with friends more, I don’t know. Whether you did or not, I certainly didn’t. I was home schooled my entire life. I had friends and sleepovers and what not, but the vast majority of my life was spent with my family. My aunt and my mother raised me. They weren’t just my parents, they were my best friends. I care more for them than I do for anything else on this planet. Leaving them behind was the hardest thing I ever had to do.

I didn’t sleep the night before I left. Not a wink. That morning when I stepped out of the car and my mother handed me my bag and I saw her and knew in my heart how long it was going to be before I saw her again, I completely lost my shit. I’ve never in my life tried to keep myself together so hard. I managed to choke back my tears after a couple escaped my grasp and I walked into the terminal. Have you ever seen your mother or father cry? Remember how that feels. I thought I would die before I got on the plane that day.

When I arrived in Los Angeles, Alan picked me up at the place in Hollywood where I was to stay for a couple of months prior to finding a more permanent place to live. He helped me run some errands and then took me out to dinner. I enjoyed it, and his company, but as soon as I walked through my door when I got home that night, I collapsed into tears. This would become a nightly routine for the next two weeks. Every night after work. How I even held it in all day eludes me looking back. I like to think that I’m a strong person and I can handle things and adapt, but that has to be the lowest point I’ve ever hit in my life. Balancing the excitement and thrills of a new city and a new life against the sorrow produced by giving up my old life. It was utterly overwhelming.

Fortunately, like things tend to do, this passed with time. I eventually stopped crying at night. I faced the fact that this was reality and I began to enjoy my new life. I made a point of remembering that my plans are to bring my mother and my aunt out here, because they also deserve a new life. I need to make enough money to help support them first, and there are very big obstacles outside the scope of this blog post that are keeping me from moving them out here in the near future, but it’ll happen eventually. Until then, life keeps chugging along, and there is far too much greatness in my new home and my new surroundings to not take full advantage of it in the meantime.

The Highs

As of August 3rd, I’ve lived in Los Angeles for six months. These days I live in a nice apartment in West Los Angeles. Geni’s office is on the famous third street promenade in Santa Monica, just a couple of blocks from the beach. Things have been going well at work. I’ve learned tons of new things and have even done a bit of Ruby. I get to use Clojure! I have amazing coworkers who include two of the smartest people I know on this planet, Justin and Alan, and I am utterly privileged to work with them. I can’t express that enough. I’m very lucky to call these guys my friends.

Lance left Geni and started working at Scopely shortly after I moved out here, but he is still in the LA area and we hang out pretty frequently. He actually took me to my first concert several months ago. It was KMFDM, a band I was unfamiliar with, and I was in a mosh pit for most of the night. Very high on the top of my shit-I’ll-probably-never-do list.

Since I’ve been here I have seen Imagine Dragons in concert twice (one of which was filmed for the August 11th, 2013 season finale of Live From the Artists Den on PBS), saw an old homeless lady take a piss on the sidewalk standing up and looking me in the eye whilst doing it, and visited Universal Studios twice. I’ve got tickets to see the first band I ever called my favorite, Panic! at the Disco, later this month.

My apartment is mostly furnished at this point. People at work have been giving me things since I got here, including a couch, a great desk, and some chairs. I slept on a borrowed air mattress for months until it broke (apparently airbeds can both not have a hole and be broken at the same time, pretty wild), at which point I bought a real bed. Once I moved the couch in, I realized that my apartment actually looked like someone lived in it. That took me by surprise. I’ve got a car now. Things are real. This is me. I live in Los Angeles. This is life.

I’ve made some mistakes since getting here. I’ve also done some things right. Moving out here was not a mistake. I like my new life. Don’t get me wrong, I get melancholic from time to time, but less and less often as time goes by. Things aren’t perfect. There are things missing from the picture, but that’s life. Life is about balancing reality with happiness and making sure you have enough of the latter, and I’m happy. I see myself with a future, and I like that.

I don’t know what the future has in store for me. Most people don’t. I think Los Angeles and my current choices are good for me, and I’m excited to see what happens in the next six months and beyond. I’m Raynes, and that’s my life.

Moving Away From Noir

| Comments

UPDATE: See the end of this post for a quote from Noir’s original author, Chris Granger. Also, here are the commits where I moved to Compojure in refheap: https://github.com/Raynes/refheap/compare/b943338cc23ff63559fa6190e74f0f39f85badb0…6ab25a24e7e669c7d6482c111bc4a44d5de1997a

This might be a bit of a sad post for some people, but most will find that it was simply long overdue and necessary. This post is a formal announcement of Noir being more or less deprecated.

First, let’s talk about what Noir is. Noir is not really a web framework. What Noir is is a collection of libraries that most people use when developing a web application. It was originally designed to make it extremely easy to get new and potential Clojure developers a website they can look at and use. It served that purpose really well.

Noir provided things like stateful session, flash, and cookie management, as well as simple things like a little validation library and a utility for hashing passwords and such using jcrypt. This what made Noir so popular. People wanted a batteries included ‘framework’ and Noir served that purpose for them.

Under the hood, Noir uses Compojure for routing. On top of it, Noir has an abstraction called ‘defpage’ that allows you to create routes statefully and then call a ‘start’ function and have it Just Work. At the time, Compojure generally required directly calling the jetty adapter and such to get a server running. You never needed to do that yourself in Noir.

With defpage came some agony as people realized that while Noir’s abstraction looks fantastic, you have no control at all over how the routes are defined and wrapped by middleware. Because of that, Noir was much less flexible than Compojure. If you’ve ever tried to have a complex middleware setup on your routes in Noir (or used Friend with it for that matter), you already know what I’m talking about. It is generally impossible to do so much as wrap a specific set of routes in middleware. This could have been added to Noir, but why bother? For the longest time, even Chris himself said that Compojure was better for these situations.

Given all of these realizations, I stopped using Noir quite a while ago. I recently even moved refheap to Compojure.

A big problem that everybody has noticed recently is that Noir is no longer moving. My buddy Chris has moved on to a bigger part of his life now, working on Light Table, and does not have time for a lot of his old projects. Noir is used by quite a few people, so I took on the role of maintainer of the project to the best of my ability, but I do not know much about Noir’s internals nor do I have the time or motivation to work on it. Neither does anyone else.

Chris and I discussed this last night, and we decided that it’s time to deprecate Noir and ask that people focus on Compojure instead. The good news is that you don’t have to give much of anything up if you move to Compojure! A while back when I started moving my own sites to Compojure, I took most of the useful libraries that were embedded in Noir and I split them out into a new library that you can use from Compojure! lib-noir is the legacy of Noir. The best thing that came out of it. It has all the useful stateful sessions, flashes, cookies, as well as the other useful libraries. In fact, the latest release of Noir depends on this library so if you’re using it, you’re already secretly using lib-noir!

For new websites, please use Compojure and lib-noir. This is pretty much just as batteries included as Noir itself ever was! You just have to learn how to write routes with Compojure. It’s easy and just as concise as it was in Noir. You don’t have to use ring-jetty-adapter and stuff, just use the lein-ring plugin to start your server. Also, if you took advantage of Noir including hiccup by default, you’ll have to have an explicit dependency on it now. No biggy, right? Right!

At this point, I imagine the biggest concern most of you have is what happens to your existing Noir website. Well, does it work? If so, you should be fine. If you plan on doing extensive work on Noir websites in the future, I recommend moving to Compojure as soon as possible.

I will not be maintaining Noir. If there is a serious bug or something that you would like to fix, open a pull request and ping me on IRC or email or something and I’ll merge and release a new version. I won’t be updating documentation or anything like that anymore, and I won’t be adding new features. Beyond that, you’re welcome to continue using Noir for the indefinite future, but keep in mind that as your application ages, it’ll be much harder to update and eventually you’ll end up having to fork Noir to update the versions of libraries it uses. Better to avoid it altogether.

Understand that there is nothing wrong with Noir, really. We just don’t think there is a good reason to keep it around anymore. Compojure and lib-noir are in such a state that they are a great and potentially better solution. We are simply moving on.

I will absolutely continue maintaining lib-noir, so if there is anything you’d like to add to it, run it by me!

Three cheers for Compojure (and lib-noir)!

Just to tack on here: If you’re using Noir now, don’t worry, everything is fine - 1.3.0 has been officially released and it’s not going anywhere. There’s nothing wrong with what’s out there now, it’s just that 1.3.0 will likely be the last release unless someone wanted to keep moving it forward. As time goes on, it likely makes sense to transition, but fortunately transitioning is pretty straightforward and Raynes can point to the commits he used to do that for Refheap. Ultimately, lib-noir + compojure gives a lot more flexibility when it comes to things like middleware at a relatively slight cost to ease of starting. Noir has always used compojure under the covers and so you’ll find that most everything you’ve learned so far will map over pretty cleanly.

When I started the project about two years ago, the Clojure web landscape looked quite a bit different and getting started was an incredibly painful process. Compojure had just split into a bunch of different pieces, there was this new “ring” thing, and trying to cobble everything together was a pretty daunting task. Since then, the Clojure web ecosystem has matured quite a bit and lib-noir fits very nicely into the direction the community is ultimately heading in. Noir still serves its purpose as a solid starting point for people who just want to get up and go with Clojure on the web, but I’ve also come to the conclusion that what we have now is just a baby step toward what we *could* be doing on the web. There are far better solutions waiting out there for Clojure, ones that don’t just look like a standard http wrapper, and that’s what we should be ultimately moving toward. We have the fundamental building blocks to build websites, it’s time we start pushing the state of the art.

I’m excited to see what we, the community, come up with.

Cheers,
Chris.

Easy JSON Parsing in Haskell With Aeson

| Comments

Yeah, I’ve been using Haskell. Wanna fight about it? Clojure isn’t everything, you know? Just most of everything. Something you may not know is that Haskell was actually my first language, but until recently I had not used it for around 4 years! Haskell was the first language that ever made sense to me, but I hopped to Clojure pretty quickly after that and there were a lot of awesome things I missed. In particular, I never really got applicative functors, monads, etc. I recently got back into Haskell for a delightful change of pace as well as to learn these things I missed.

Haskell has more or less been a joy to work with. Two areas I found extremely hard to get into are JSON parsing and HTTP clients. I’ll be writing a blog post about the latter soon, but this post is going to focus on JSON parsing.

In Clojure, we can just parse a JSON object into a Clojure map. Hash maps in Clojure are heterogenous in nature and the keys and values can be any type. We don’t have this looseness in Haskell, and the way its type system works means we have to do things differently.

Usually, you’re going to want to define some data types that you will populate with your parsed JSON. Usually, JSON maps to types very easily. First of all, lets get some JSON to parse. Let’s use some JSON returned by refheap’s API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ http https://www.refheap.com/api/paste/1
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 226
Content-Type: application/json;charset=utf-8
Date: Tue, 27 Nov 2012 08:39:26 GMT
Server: Jetty(7.6.1.v20120215)

{
    "contents": "(begin)", 
    "date": "2012-01-04T01:44:22.964Z", 
    "fork": null, 
    "language": "Clojure", 
    "lines": 1, 
    "paste-id": "1", 
    "private": false, 
    "random-id": "f1fc1181fb294950ca4df7008", 
    "url": "https://www.refheap.com/paste/1", 
    "user": "raynes"
}

This is a simple one-level JSON object.

Aeson uses Text instead of regular strings for everything, so to make things a lot easier on us, we should use a language extension that overloads strings so that we can just write literal strings and they will work for where Text is expected:

1
{-# LANGUAGE OverloadedStrings #-}

Let’s go ahead and throw some imports in to start:

1
2
3
import Data.Aeson ((.:), (.:?), decode, FromJSON(..), Value(..))
import Control.Applicative ((<$>), (<*>))
import qualified Data.ByteString.Lazy.Char8 as BS

Now here is the interesting part: we need a type to contain our parsed json info. Take a look at our JSON. It is… a paste! A paste is a thing. It is a thing that always has certain properties. It maps perfectly to a data type:

1
2
3
4
5
6
7
8
9
data Paste = Paste { getLines    :: Integer
                   , getDate     :: String
                   , getID       :: String
                   , getLanguage :: String
                   , getPrivate  :: Bool
                   , getURL      :: String
                   , getUser     :: Maybe String
                   , getBody     :: String
                   } deriving (Show)

We defined the Paste type with record syntax to make it easy to get pieces of it out and to remember what each field is. All of this should be self explanatory. Note that the user is wrapped in Maybe because anonymous users can create pastes and in those cases there wouldn’t be a user at all, so it’d be Nothing.

Now here comes the complicated part: we need to define an instance of the FromJSON typeclass for our new Paste type. If we do this, we will be able to decode our json directly to our Paste type. Aeson also has a ToJSON typeclass for if we wanted to write code to convert our Paste type back to JSON, but we’re not interested in that. Let’s write our instance:

1
2
3
4
5
6
7
8
9
10
11
instance FromJSON Paste where
  parseJSON (Object v) =
    Paste <$>
    (v .: "lines")     <*>
    (v .: "date")      <*>
    (v .: "paste-id")  <*>
    (v .: "language")  <*>
    (v .: "private")   <*>
    (v .: "url")       <*>
    (v .:? "user")     <*>
    (v .: "contents")

Unfortunately, to really understand this example you need to have knowledge of applicative functors. Explaining those and the above use of them is waaaaaay beyond the scope of this post. I’ll try to make some sense of it though.

Let’s break things down. The first question you’ll probably ask is “What in tarnations does .: do!?!?!”. In this case, it looks inside our object for a JSON key called "lines" and plucks the value out. You’ll notice that we also have .:?. The difference between it and .: is that .:? allows for the key to not exist or be null. It returns a Maybe. Remember that that is precisely what we need for our possibly non-existing user key.

As far as the applicative functor stuff, you can more or less see what is happening. Picture it like this: each argument to Paste is in a box. The operator magic is taking each argument out of its box and applying Paste to it. The end result is a new Paste. If any of the extractions with .: or .:? fails, the result will be Nothing and we wont get a paste back. Let’s try this out. First define our JSON string. This needs to be a bytestring:

1
2
3
4
5
*Blah> :load "blah.hs"
[1 of 1] Compiling Blah             ( blah.hs, interpreted )
Ok, modules loaded: Blah.
*Blah> let json = BS.pack
"{\"lines\":1,\"date\":\"2012-01-04T01:44:22.964Z\",\"paste-id\":\"1\",\"fork\":null,\"random-id\":\"f1fc1181fb294950ca4df7008\",\"language\":\"Clojure\",\"private\":false,\"url\":\"https://www.refheap.com/paste/1\",\"user\":\"raynes\",\"contents\":\"(begin)\"}"

Next, we’ll decode into our Paste type:

1
2
3
4
5
*Blah> decode json :: Maybe Paste
Just (Paste {getLines = 1, getDate = "2012-01-04T01:44:22.964Z", getID = "1",
getLanguage = "Clojure", getPrivate = False, getURL =
"https://www.refheap.com/paste/1", getUser = Just "raynes", getBody =
"(begin)"})

Awesome! As you can see, our result is wrapped in Just. If our JSON didn’t contain necessary data or was somehow not well formed, we’d get back Nothing instead. Let’s extract the date from the JSON.

1
2
3
*Blah> let (Just x) = decode json :: Maybe Paste
*Blah> getDate x
"2012-01-04T01:44:22.964Z"

Fantastic. You’ve just parsed your first JSON in Haskell. Give yourself a pat on the back.

Let’s do something a little more complicated now. What if we don’t want our date to just be a string? What if we want some sort of date type? What if we want UTCTime? Let’s do that. First, we need to import a few more things. Add these imports:

1
2
3
4
import Data.Time.Format     (parseTime)
import Data.Time.Clock      (UTCTime)
import System.Locale        (defaultTimeLocale)
import Control.Monad        (liftM)

Now, let’s write a simple little function for parsing dates in the format that refheap uses. This example is taken from haskheap and you do not need to understand how it works if you don’t already know or care, the important part is how we use it later.

1
2
parseRHTime :: String -> Maybe UTCTime
parseRHTime = parseTime defaultTimeLocale "%FT%X%QZ"

This function takes the string date from refheap’s json and returns Maybe UTCTime. It is wrapped in Maybe because it could fail if the date isn’t well-formed. Now, let’s change our Paste type to expect UTCTime instead of a String.

1
2
3
4
5
6
7
8
9
data Paste = Paste { getLines    :: Integer
                   , getDate     :: Maybe UTCTime
                   , getID       :: String
                   , getLanguage :: String
                   , getPrivate  :: Bool
                   , getURL      :: String
                   , getUser     :: Maybe String
                   , getBody     :: String
                   } deriving (Show)

Excellent. Now all we need to do is change our FromJSON instance.

1
2
3
4
5
6
7
8
9
10
11
instance FromJSON Paste where
  parseJSON (Object v) =
    Paste <$>
    (v .: "lines")                  <*>
    liftM parseRHTime (v .: "date") <*>
    (v .: "paste-id")               <*>
    (v .: "language")               <*>
    (v .: "private")                <*>
    (v .: "url")                    <*>
    (v .:? "user")                  <*>
    (v .: "contents")

Easy enough, right? The Parser type that .: returns is a monad, so we just lift our parseRHTime function into it. Now let’s parse our JSON again.

1
2
3
4
5
6
7
*Blah> :load "blah.hs"
[1 of 1] Compiling Blah             ( blah.hs, interpreted )
Ok, modules loaded: Blah.
*Blah> let json = BS.pack "{\"lines\":1,\"date\":\"2012-01-04T01:44:22.964Z\",\"paste-id\":\"1\",\"fork\":null,\"random-id\":\"f1fc1181fb294950ca4df7008\",\"language\":\"Clojure\",\"private\":false,\"url\":\"https://www.refheap.com/paste/1\",\"user\":\"raynes\",\"contents\":\"(begin)\"}"
*Blah> let (Just x) = decode json :: Maybe Paste
*Blah> getDate x
Just 2012-01-04 01:44:22.964 UTC

Yay! UTCTime! Wee!!!

So yeah, it’s actually pretty simple. Usage of Aeson isn’t exactly the most well documented thing in the world, and if you don’t at least understand applicative functors, the examples can be really intimidating. If none of this makes sense, go dig into LYAH for a while. In particular, the typeclasses through to the applicative functors chapters will help immensely.

Okay, so the above decode-straight-to-a-type sort of thing is the most common way of working with JSON. But you don’t always need or want to define a new type just to grab a bit of information from some JSON. What if our code only cared about the number of lines in a paste? We could write a Lines data type and then an instance, but is it really worth it? We can just extract that piece out. Let’s rejigger our imports again:

1
2
import qualified Data.HashMap.Strict as HM
import Data.Attoparsec.Number (Number(..))

Now, let’s write a function to extract the number of lines from the json.

1
2
3
4
5
6
getRHLines :: String -> Integer
getRHLines json =
  case HM.lookup "lines" hm of
    Just (Number (I n)) -> n
    Nothing             -> error "Y U NO HAS NUMBER?"
  where (Just (Object hm)) = decode (BS.pack json) :: Maybe Value

This isn’t nearly as complicated as it looks. It’s mostly just a lot of destructuring. The meat of the example is that we are decoding the json to Maybe Value instead of our own type. Our JSON is a big JSON object, and aeson represents this as a hashmap. We can just look the lines key up in it! Note that the Number type here is a wrapper around the Number type from attoparsec. It is just a fancy type for representing different numbers with decent precision. In this case, it represents an Integer (I), so we’re destructuring on that constructor.

Well, that’s about all there is to it. There is also a funky trick for automatically defining instances, but I’m not a big fan of that and it is outside the scope of this post.

Here is the completed code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{-# LANGUAGE OverloadedStrings #-}
module Blah where

import Data.Aeson             ((.:), (.:?), decode, FromJSON(..), Value(..))
import Control.Applicative    ((<$>), (<*>))
import Data.Time.Format       (parseTime)
import Data.Time.Clock        (UTCTime)
import System.Locale          (defaultTimeLocale)
import Control.Monad          (liftM)
import Data.Attoparsec.Number (Number(..))
import qualified Data.HashMap.Strict as HM
import qualified Data.ByteString.Lazy.Char8 as BS

parseRHTime :: String -> Maybe UTCTime
parseRHTime = parseTime defaultTimeLocale "%FT%X%QZ"

data Paste = Paste { getLines    :: Integer
                   , getDate     :: Maybe UTCTime
                   , getID       :: String
                   , getLanguage :: String
                   , getPrivate  :: Bool
                   , getURL      :: String
                   , getUser     :: Maybe String
                   , getBody     :: String
                   } deriving (Show)

instance FromJSON Paste where
  parseJSON (Object v) =
    Paste <$>
    (v .: "lines")                  <*>
    liftM parseRHTime (v .: "date") <*>
    (v .: "paste-id")               <*>
    (v .: "language")               <*>
    (v .: "private")                <*>
    (v .: "url")                    <*>
    (v .:? "user")                  <*>
    (v .: "contents")

getRHLines :: String -> Integer
getRHLines json =
  case HM.lookup "lines" hm of
    Just (Number (I n)) -> n
    Nothing             -> error "Y U NO HAS NUMBER?"
  where (Just (Object hm)) = decode (BS.pack json) :: Maybe Value

Not half bad for 44 lines, eh? It isn’t nowhere near as intuitive as doing the same things in Clojure is, but that’s because Clojure doesn’t have Haskell’s type system. JSON parsing in Haskell is necessarily complicated, but Aeson does an excellent job of making it not-that-hard. What Aeson really needs is some serious beginner-oriented documentation.

This is the first Haskell blog post I’ve ever written and is based on the first Haskell code I’ve written in about 4 years. Please be gentle. If anything is wrong or can be improved, please let me know via email or a comment! I’ll be writing a blog post about http-conduit soon because I also found it a huge pain in the ass to work with. Stay tuned.

Help Fund My Trip to the Conj

| Comments

!!! GOAL REACHED! WOOHOO! LOOK FOR A FOLLOW-UP BLOG POST SOON WITH A LIST OF -DONORS !!!

Hello there boys and girls of all ages, shapes, and sizes. It’s your old friend Anthony Grimes (Raynes) here with an appeal.

You see, I didn’t plan on going to the Clojure Conj conference this year. A sad decision it was, I knew I wouldn’t be able to pay for a ticket as well as airfare and a room, since I currently only work part time as an intern with Geni. I could have submitted a talk, but I decided against it so that I could focus on things other than slideshows for a while.

But hey, I should have known that wasn’t the end of it. When has the Clojure community ever let me miss out on something? Never is when. This time is certainly no different. I wandered into my email account about a week ago and there sat an email from Lynn Grogan. She was asking if I was going to the Conj. She said that “at least one person wants to donate their ticket to you”. As spectacularly impossible and amazing this was, I had to email her back saying that I still wouldn’t be able to cover airfare and a hotel room on such short notice.

Less than 30 seconds later, good ol’ Chas Emerick pings me on IRC and we start jotting out how I can get there. I came to learn that my good friend Carin Meier (an avid 4Clojure contributor and all around good person) was the person who was donating her ticket. Unfortunately she is unable to go to the Conj this year and didn’t want her ticket to go to waste. She thought of me! Everybody give her a round of applause!

So Chas and I discussed things for a while and we decided that I should follow in Laurent Petit’s footsteps and hold a fundraiser of my own. If you’ve been around Clojure for a couple of years (or at least read hacker news), you will probably remember that this isn’t the first time the Clojure community has helped me exceed my own limitations and do something great. In fact, my first plane ride was on a community funded trip to the first Conj when I was 16. Needless to say, those were some of the most memorable and amazing days of my life.

In summary, I only found out a few days ago that I now have a free ticket to the conj. I had no intentions of going so I have no money at all saved up for the trip. Even more problematic is that plane tickets are now higher than usual. Here is what I’m looking at:

  • Hotel room at the conference booked from the 14th to the 18th of November at $134 a night: $536
  • Airfare roundtrip from Birmingham, AL to Raleigh, NC at $368: $368
  • I’m going to raise the ceiling a bit to help cover a ticket for my mother (who really enjoys these trips), food and drink, and a little emergency money just in case. $400

Grand total: $1304. I have set the goal to an even $1300.

Your next question may very well be “Who the hell are you and why should I donate?”. My name is Anthony Grimes. I’ve been around the Clojure community since I was around 15 years old and have developed a close relationship with its members because of it. I am the author of numerous projects, including some well-known ones such as

  • TryClojure, a sandboxed online REPL + mini tutorial for new Clojurians.
  • Refheap, a pastebin written in Clojure that aspires to exceed the standard set by gist, with a focus on usability for Clojure users.
  • Clojail, a Clojure sandboxing library that powers 4Clojure and TryClojure.
  • lazybot, an IRC bot written in Clojure with Clojure evaluation and a host of other features. It is no doubt the best bot evars.

You can see the rest of my projects and activity on github.

In addition to my own projects, I am an avid proponent and contributor to

  • The leiningen build tool, having contributed some built-in commands and numerous plugins, including lein-newnew
  • 4Clojure, an excellent learning tool for Clojure developers that poses problems and asks you for solutions.
  • The flatland organization, a whole host of libraries and tools written by a group of friends and colleagues at Geni.

I spoke about clojail at last year’s Conj.

At this point in time, I am 18 years old and I live in a small town in Alabama called Eldridge.

So that’s me and this is my appeal. This trip would be an excellent opportunity to me to learn about and experience new things as well as keep in touch with the community and discuss projects/ideas. Any donations are appreciated and if you leave your name with your donation I will list it in a follow-up blog post and personally dance for you at the Conj1.

Paypal doesn’t really have anything in the way of progress bars and the like, so I’m going to update this blog post manually. Don’t expect the total to rise immediately after you donate. Also keep in mind that the paypal account is my mother’s (I don’t have a personal account because I rarely use paypal), so the name listed is Connie Simpson.

Button removed! Goal reached!

Goal reached at 5:30PM: $1320.90

1: No, I wont.

Meet Clojure Update: I Don’t Have Time to Write This Blog Post

| Comments

It has been quite a while since I updated everyone on the progress of my book, Meet Clojure, and several people have asked about it over the past 2 weeks, so I think now is the time for an explanation.

As everyone knows, I’ve been working on Meet Clojure for over a year. Unfortunately, for the vast majority of that time I haven’t actually had the time to work on it. Not to say I didn’t ever get anything done. To the contrary, there are several chapters written. But in the world of book writing, there is a huge difference between a chapter being written and a chapter being finished. I am not a perfectionist, but this book is meant to be good, so I’m generally unsatisfied with everything I’ve written and will eventually need to rewrite most of it.

But what needs to be done isn’t the problem at all. The concern is what is keeping it from being done. When I got my publishing deal with No Starch was right about the time that I got a job at Geni. For a while there I was able to work just fine, have a relatively decent life on the side, keep up with personal projects, and spend enough time on the book to keep things moving along (slowly but surely).

My biggest problem is arguably my biggest asset: I try to do too many things at once. Go look at all the stuff on my Github page. I overwhelm myself before I realize I’m doing it. I have to fight with myself to figure out ways to focus on specific things for specific amounts of time and try to not neglect the other things. Refheap is an excellent example. There is so much I want to do with it but it progresses slowly because if I focused on it, other things would suffer.

Aside from all of this, I want to be able to focus on what I have to do where I work as well. If I’m stressed out, I’m not doing my coworkers any good. I wont get good code written and I wont be able to keep the standards that got me the job in the first place.

And that’s the goal behind it all: stress management. How much can I do and how often can I do it without being exhausted, stressed out, and worthless to everybody? I spent a lot of time thinking about it and a lot of time talking to close friends and trusted colleagues, and I’ve decided that, for right now, the book is too much for me to handle.

Okay, stop panicking. Calm down. Deep breaths. Let me explain myself.

There are a lot of Clojure books around. The latest one Clojure Programming by my good friend Chas Emerick is a fantastic one. I talked to my buddy (and technical reviewer) Chris Granger about this before I made any decisions, and one thing he said that helped me make the decision was: “You can contribute to the Clojure community better without the book right now.”. He is correct. Without the book, I have time to work on my various libraries and tools and help out in whatever capacity is needed. We have plenty of good books, and we’re not going to suffer any dramatic losses if mine isn’t completed right now.

I still intend to write this book

This is the most important part of this blog post. I am not under any circumstances giving up the book. I still think the book will be an important addition to the Clojure bookshelf. I simply do not have the time or energy to make it happen at the moment.

My plan is just to wait. I don’t know exactly how long, but I’m just going to wait for a crack. A point where my life is not so utterly insane. I’m going to work on my personal projects, do a great job at Geni, and spend as much spare time as possible with my mother and my aunt, because I’m likely going to be moving far, far away in the not so very distant future. These are the things that are most important to me at the moment.

Future plans

The first thing I did was discuss these things with my amazing publisher, No Starch Press. I have the most amazing editor ever in Keith Fancher, and he is extremely open to what I have to say and how I feel. He was entirely sympathetic. I sent the email with the expectation that they would tell me to bugger off and write the book myself, but that’s the precise opposite of what he said. I certainly plan to pick the book back up when life allows (when I can do a good job on it), so he proposed that we set a date where we can touch base in the future. I proposed 6 months and he agreed.

So rest assured everyone, the book is going to happen. I just can’t tell you when. For the time being, I am not actively working on it. When I’m able to pick it back up again, I’ll be sure to let everyone know.

Defining Life Based on Who You’re Stuck in a Room With

| Comments

I turned 18 in February of this year. I’ve long known that hitting that milestone would mean a lot major life changes in quick succession, and I have prepared to be overwhelmed. I’ve been told that being overwhelmed is the only logical human thing to experience when these sorts of things begin to happen. I’ve got to say, it’s one hell of a ride, but it’s one I’m very happy to be taking.

Work

I’ve been working with a wonderful company called Geni for the past year. Geni is a genealogy website dedicated to building a family tree of the whole world. You make an account and create your family tree.

Around two years ago, I was lucky enough to meet and become good friends with Justin Balthrop and Lance Bradley, both engineers at Geni. They had just created the cake build tool and I was one of the first users. The first experience I remember with these guys was me arguing with them over a feature cake had that I did not like, which was that it would start a swank server by default whenever you ran a command. I can’t remember the details of why this was a problem with me, but the end result was that they made the feature more configurable and off by default.

Days go by, we become friends. We met in person for the first time at the first Clojure Conj conference in late 2011. We spent the entire conference together. We had a lot of fun.

Eventually, Lance and Justin began talking about the possibility of me working at Geni as an intern. I think I was still 16 when I had my phone interview with the then-CTO, Amos. Several months passed while details were worked out. Amos left the company and Justin was promoted to CTO, which gave him more wiggle room for bringing me on as an intern quickly. I started in March of last year.

Oh my, what a wonderful year. 17 years old, working part time with Clojure from my own home all the way across the country. Even making money! Lance and Justin have taught me so much and given me so much experience. They’ve helped build my skill and my confidence in my skill, and I don’t think I’d be even remotely the man I am right now without their ongoing influence. I don’t think they’ll ever know what they’ve done and continue to do for me.

Turning 18

Turning 18 was always an important milestone for my Geni work. As long as I was a minor and still in high school, I could only work part time and the legality of things would be complicated.

Our plan was to fly me out to Los Angeles when I turned 18. I would work in the office for a week face to face with my coworkers and experience LA. A few weeks before I was meant to make this trip, I freaked out for a few days. Moving away from home is the expected end result of all of this. Unfortunately, there are circumstances preventing me from relocating my family at this point in time, and thus this is something that I would have to do alone.

Needless to say, this scared the hell out of me. So much so that I talked to Lance and Justin and pleaded for a way to continue working there and not have to uproot. Justin encouraged me to relax and just come out there for the trip and talk again after LA was no longer an imaginary place. His and Lance’s calm regarding this matter along with encouragement from my family to make this happen calmed me down significantly. I still wasn’t sure about moving, but the possibility stopped being ridiculous and began to make sense.

Los Angeles

The plan became a reality last week. I stepped on my flight on the morning of Friday the 13th. This was the first flight I had ever taken by myself, and it would lead me to a place farther away from home than I had ever been before.

I had a connection in Nashville where I got on a plane to Los Angeles. After this uneventful 4 hour flight, I found myself on an escalator down to a man waiting for me with my name on a card. This man drove me to the studio where I was to stay until the 21st. What makes this drive notable is that my best friend Alan (also an engineer at Geni) sent me a text message saying “Welcome to LA!”. I smiled so hard that I’m surprised my teeth didn’t fall out. My entire experience was braced on this text message. Los Angeles stopped being this scary place where I would be alone. Much to the contrary, I was surrounded by friends; the greatest people I’ve ever had the privilege of knowing. And they all wanted me there. They were all waiting for me to arrive. If you’ve never experienced this, you’re missing out.

I was picked up shortly after arriving by Lance and carted to the Geni office on Sunset Boulevard for the first time. They had set me up a desk and an amazing Aeron chair. Lance gave me a tour of the office and then he, Justin, Alan, and I all headed across the street to BOA Steakhouse for a fantastic dinner.

This was the beginning of a whirlwind weekend where Lance showed me the most amazing things I’ve ever seen. He gave me the tour of a lifetime and conversation that I will never forget. Alan came along with us for a lot of the weekend activities. Notably, Lance showed me Hollywood, Santa Monica, and Venice. I had never seen the ocean before, so it was mind blowing. We all took our shoes off and stood in the cold waters of pacific tide at Venice beach. I’ve never had so much fun in my life. Not for one second did I think of home, leaving my family, uprooting, changing. All that mattered was how I felt, and I felt amazing.

We did so many things that weekend that I couldn’t bring them all to mind in order to list them even if I tried. Notably, we saw a wonderful movie called The Chronicle and Lance and Alan took me to my first 3D movie (Wrath of the Titans) which I thoroughly enjoyed.

Monday begins my first 40 hour week at Geni, working in the office face to face with my coworkers. I felt at home the moment I plugged my laptop into the monitor on my desk. The conversations between my coworkers are smart and well worth listening to, and we have plenty of fun in the office as well. Light Table was kickstarting at the time, so we had lots of conversation about that and we followed developments closely.

During the week, Lance and I would sometimes do stuff after work. Lance took me to the hills one night and showed me the most amazing view of the city from above. The lights go on forever and the cars appear to be infinite. It is like an ocean on land, and it surrounds you on every side. It is inspiring and overwhelming in its beauty and is one of my highlights from the week.

I got a lot of work done during the week. I had never bought into the whole you-gain-a-lot-by-working-face-to-face thing, but I have to say, I believe it now. It is a lot easier to get things done and to concentrate when you’re in an office setting. If you need something from somebody, you find them and talk to them. There are few distractions. I highly value an office setting now and I’m excited at the prospect of doing it every day.

By Thursday, two nights before the morning I was to leave, I found myself in a position that I never expected myself to be in: I did not want to go home at all. I was enjoying it so much that the fact that I had to go home at the end of the week had been entirely an afterthought. It was saddening when the time finally came.

On Thursday, Lance and I left work early and drove to Malibu. Lance has suggested that Venice beach was not a good first beach experience. I didn’t know what he meant until I saw the beaches of Malibu. They were so utterly majestic! The first thing I noticed was that I could, for the first time, noticeably smell the ocean air. We went below Point Dume and climbed over rocks to tide pools. The scenery took my breath away.

Earlier in the day, Justin told me he wanted to talk about my trip and my plans for the future. We went to a private room and talked. He was concerned about putting pressure on me. He asked me how I liked it there and if I had decided whether or not I wanted to come work at Geni full time and live in LA. I was telling him yes in the blink of an eye.

Things are set in motion now. I get my diploma on the 25th of this month (April), and Geni will be able to make me a full time offer. In the next couple of months, I’ll move to Los Angeles and begin a life on my own.

Stuck In A Room

There is an episode of House where House talks with a patient (who had been raped and was pregnant) who he is reluctant to treat. There is a part where the girl says something along the lines of “All life is is a series of rooms, and who you’re stuck in those rooms with adds up to what your life is.”. This is what comes to mind when I think of this trip and my future.

Moving to LA, I will not be alone. In fact, I’ll be stuck in a series of rooms. The important thing is that there is nobody in this world who I would rather be stuck in those rooms with. I’ve got the best friends in the world, and I have the luxury of them also being my coworkers. I’ve never wanted to be stuck in a room so much in my life.

My friends have given me the best and most important week of my life. It was a life-changing trip that I will never forget. It has and will shape my life and future. A follower on twitter mentioned that it is amazing when things click, and I have to say that I agree.

I’m very excited about my future. My life is about to change radically, and I’m okay with it. I have choices and options I’ve never had before, and I see my path in front of me. It is going to be one hell of a ride, but it is a ride that I’m happy to take. Lance, Justin, Alan, thanks for making this a reality. Thanks for making things easy. Thanks for giving me an amazing new room to get stuck in.

Thanks for reading.

I Code With Things and Stuff

| Comments

A lot of radical changes in my development environment resulted in someone asking me if I’d write a blog post about it. I was already considering doing that, and the interest of at least one person is motivation enough to actually do it.

Background

I used Emacs for around two years. It started back in my Haskell days. You know how Lispers love Emacs because it has SLIME? Haskellers seem to love Emacs because it can handle Haskell’s complex indentation rules (rules that aren’t really rules but still shouldn’t be broken).

When I started using Clojure, I was lucky enough to already have some Emacs under my belt and so I continued using it.

Emacs

Oh how I love Emacs. When I used Emacs, I even used it as my IRC client via ERC. ido-mode was my lord and savior and a day without it was a day spent in the deepest bowels of hell.

When you use Emacs for a language like Clojure, you tend to get smug towards people who use other editors (particularly Vim) because you have SLIME, the Superior Lisp Interaction Mode Environment Blah Whatever. It is a fantastic development environment for Lisp languages (including Clojure) that provides debugging (I don’t think this actually applies to Clojure yet), completion, interactive development inside of Emacs, and all sorts of other stuff that makes birds sing and babies be born.

Though I used and loved Emacs, I almost never used SLIME. Don’t get me wrong, I respect and understand why it is so important to people, I just never really used it. If I did use it, it was because having a REPL inside of my Emacs window was more convenient than switching to a terminal window to enter some code. Plus, when you use SLIME (or inferior-lisp which is a completely different and simpler thing), you can send code from one buffer to another without copying and pasting. It makes things really quick and easy. That’s all I ever used SLIME for.

The greatest thing about Emacs is just how much you can do with it. The fact that SLIME is possible in the first place and that it can work out so well is spectacular. Emacs is built around a Lisp called elisp. As such, Emacs is probably the most extensible editor that ever has been or ever will be. You can make Vim do magic tricks, but Emacs really can pull a rabbit out of a hat.

And that’s what has always bothered me. When people talk about Vim vs Emacs they end up focusing on the least important things. You can’t even have a discussion about the merit of one or the other without a flurry of childish remarks. Sure, Emacs is an operating system. That’s the point. Emacs is an execution environment for a Lisp. It is designed for you to be able to do anything with it. That isn’t a flaw. It is insignificantly bigger than Vim and insignificantly more resource-intensive because it is supposed to be.

So, what about important things? Key chords versus colon commands? Sure, this one is relevant. A lot of people dismiss Emacs because of it being driven by keyboard shortcuts off of a number of modifier keys. In particular, a lot of people complain of “Emacs pinkie” because of the position of the control key and the number of times an Emacs user has to use it to get anything done. I can understand this complaint, though I’ve never experienced problems related to it. As a matter of fact, I’ve only had control mapped to caps lock for one year. My work sent me this laptop with it already remapped and I decided to leave it like that. I got used to it so it wasn’t in my interest to switch it back. I’m still not sure I’ve gained anything by having it moved there.

But yes, key chords vs colon commands does matter to some people and I can understand why.

Experimentation

I like trying new things in my development environment. New editors, new IRC clients, new color schemes, new terminal emulators, etc. I get bored. I recently started playing around with text editors with no real intention of moving away from Emacs.

First of all, a friend and I have been working on RefHeap, a pastebin with an API. The first thing I did was write an Emacs plugin (library?) for it. A lot of people wont even consider a pastebin unless it has support for their editor, so I figured hey, I should just use as many popular editors as possible and write a plugin for all of them. Next stop: Sublime Text 2.

Sublime Text 2

At first glance, this editor is beautiful. It has the prettiest indent guides I’ve ever seen and lovely syntax highlighting. It has an excellent set of themes including the full set of tomorrow night themes which I used the most at the time. It is also a highly extensible editor. Plugins are written in Python and aren’t very difficult to write if you can read an existing plugin or manage to find up-to-date information about them.

Unfortunately, it just doesn’t seem to have a very good editor. Trying to edit Lisp code in it is so painful that it is nearly impossible. It doesn’t know how to auto-indent even remotely properly and the Clojure syntax file that comes with ST2 breaks on regexes with escaped double quotes. I fixed that with a guy’s recommendation from twitter, but it was a bandaid on an infected wound.

The thing that bothers me the most about Sublime Text 2 is the way you open files with it. In Emacs and Vim, you can execute a command and type a path to a file anywhere on the harddrive with completion and interactive features (see ido-mode for Emacs and wildmenu for Vim). In ST2, you have two options for opening files:

  • You use the operating system’s Open File dialog.
  • You use the goto anything feature which lets you type a path and gives you fantastic fuzzy completion, but only works relative to your current directory, meaning you can’t be in /Users/anthony/foo and open a file in /Users/anthony/ like this.

Also, ST2’s Open File dialog is completely separate from its Open Folder function. If you want to open a folder instead of a file, you have to use that dialog. Oh, and there is no keyboard shortcut for this.

All in all, the operating system’s open file dialog is a really weak way for a programmer to navigate the file system to open the file he needs. There is nothing in ST2 stopping this from being implemented AFAIK, but I guess I’m the only one who thinks what is done now is completely insane. Separating opening files and opening folders and forcing it to be done via a OS dialog is just not something I’m prepared to live with.

I actually used Sublime Text 2 for about a day and a half until I really had to edit some Clojure code. There was just nothing to be done. I like Sublime Text 2, but it is pretty worthless for Clojure. Since RefHeap’s primary market is Clojure programmers and Sublime Text 2 users in the community are a very, very small minority, I just decided to call it quits on that. I will absolutely revisit this (it is really easy to write a RefHeap plugin in Python) if ST2 ever becomes better for Clojure and I can tolerate it long enough to test such a plugin.

I’d like to add that my opinion of ST2 is entirely based around its support for Clojure. From what I saw, it is an excellent editor for other languages such as Python and Ruby. This makes perfect sense because the author and majority of contributors (to the parts that you can contribute to) use these languages and don’t use Clojure. I expect that the Clojure portion of things will get more love as it gets more popular in the Clojure community.

Vim

My next stop was Vim. This is where things get interesting. VimL is the most horrid extension language for an editor that I have had the misfortune of working with. The thing is, Vim is a fantastic editor. I don’t know what the author was thinking when he designed this language, but I can only assume it was done during a binge drinking contest.

The only salvation is that there are Vim interfaces for a number of languages, including Scheme, Ruby, and Python. Unfortunately, you still have to write some VimL to glue it all together, but very little. The most important stuff can be written in one of those decent languages and you can generally keep your sanity. Seriously, go look at gist.vim, a plugin for Vim for the Gist API. It is pure VimL and a little over one thousand lines. No thanks.

I used Vim for a day and then I wrote that damned plugin. I dove in head first. The most information I could find for the Vim interface to any given language was for Python, and I was equally oblivious to all of these languages so I went with it. The actual Python part of things was dead simple. I spent maybe 3 hours on it (having not written a line of Python before). Then I spent another day and a half on the VimL glue part of things and I had a very nice and usable plugin. It was great!

At this point, I stopped caring about editors and was more concerned with how much fun I had with Python! I don’t very often just write shit in random languages just because I can, so it was nice to do new things. So I began having crazy thoughts to justify a rewrite in Ruby. Everybody loves Ruby! Nobody likes Python1! Let’s do it in Ruby!

So I did it in Ruby. This time, I wrote a whole API library first because I knew I’d be using it for more than refheap.vim. That was 6 different kinds of fun. As a bonus, I wrote a command-line tool for RefHeap as well. The actual Vim part of things was easy because the VimL glue was already written from the Python implementation.

I had lots of fun doing this, and it took me several days to do it. I used Vim for all of it, and that’s where things got interesting. I really liked Vim. I used Vim for about a week and a half probably 6 months before but gave up on it for Clojure development for one simple reason: it is not as smart as Emacs about indentation.

In Emacs, when you press tab, it indents exactly how much it is supposed to be indented. You can press tab for a month and it’ll only indent to what is correct for that language. Now, this varies for languages like Haskell because there is more than one correct indentation, but this kind of variation does not exist in Lisp and thus Clojure. Where this really begins to show is in an example like this:

1
2
3
4
(defn foo []
  (let [x]
    (y x)
    (z x)))

What happens if we want to take the let out of this code?

1
2
3
4
(defn foo []

    (y x)
    (z x))

Uh oh. Now what? We need to somehow reindent this whole thing so that that the two forms are lined up against the defn now that the let is gone. In Emacs, I would have walked through this hitting tab which would reindent each line in turn for me. But Vim isn’t smart about indentation it knows what to do when I hit return and insert a newline, but if I hit tab some more, it’ll indent some more. I didn’t think Vim had an answer to this until Chris Granger, a Clojurian vimerman, told me the secret to life, the universe, everything.

Vim has a concept of ‘text objects’. Basically, this is a way to intelligently select an area of text based on what it is surrounded by. This is fantastic for Clojure and Lisp in general because everything is surrounded by parentheses. So, to reindent this code, we can do =i(.

1
2
3
4
(defn foo []

 (y x)
 (z x))

Bang! And for the line that is left, we only have to hop down a line and hit dd, which deletes the line. This one single command changed my entire opinion of Vim.

Oh yeah, and I was really attached to paredit in Emacs. Bang!. Yes, this works really really well. It has all of the most important commands (for me, anyways) and it keeps things balanced. It isn’t quite as polished as the Emacs version, but it does work.

So, somewhere along the way, I became a Vim user. I haven’t used Emacs in at least two weeks, probably 3, and I am wildly productive in Vim. I never really used editor commands in Emacs (because I never remembered them long enough to use them for anything significant, which is probably because they took longer to enter than just doing the stuff manually).

Will I continue to be a Vim user forever? I thought I’d always use Emacs, but that turned out to not be the case. I do not want to go back to Emacs and do not see myself doing so in the near or distant future. I might find a reason to do so tomorrow and I might never find a reason to do so. We’ll see.

I’ve got one thing to add to this: I have nothing against Emacs. Seriously guys, you don’t have to hate one in order to prefer the other. If I had a good reason to use Emacs now, I would. I just started using Vim and realized I liked it and that I’m very productive in it. Emacs did its job just fine and I have no animosity towards it.

So, my development setup

This was supposed to be a post about my development environment but it turned into a really long post about how I got here. I think that is important. I need people to understand why I use the things I do because that is wildly more important than what I actually use. So, without further ado, here is what I’m using for development today and how I’ve got it set up.

Software

First of all, Vim. The first thing I did when I started using Vim was install janus. It gave me a bunch of useful keybindings out of the box and a whole lot of useful plugins that I probably wouldn’t have found otherwise. The most useful ones I’ve found so far are CtrlP, NERDCommenter, NERDTree, and Fugitive (oh em gee this is awesome). The most useful thing I’ve found not included with Janus is tabular.vim.

Also useful from Janus is that it bundles some plugins for highlighting markdown, mustache, haml, sass, scss, better Javascript, and git commits. Janus really is a good way to get started. You get basically everything you need and you don’t have to go hunting for how to do it.

I know what you’re interested in is my Clojure setup, and I’m probably going to disappoint you with it. I use VimClojure, and the first thing I did was delete anything even remotely related to nailgun. Remember I said I never really used SLIME in Emacs? I haven’t even bothered trying to do anything similar in Vim. I believe the author is rewriting the stuff for nREPL, and I’ll probably give it a go once that is done, but I’ll probably never use it much. I actually like lein repl and I use it. I do tons of interactive development, I just don’t do it in my editor. Am I missing out? Probably. Do I care as long as I still get things done and am productive? God no.

Besides paredit.vim, that’s it for my Clojure setup. Just VimClojure’s syntax highlighting and indentation stuff and Leiningen. Clojure is simple. Don’t need much more than that.

Oh, I also use OS X. The Vim I use is MacVim and my terminal emulator is iTerm2, simply because it is less quirky than Terminal.app.

My color scheme is solarized dark unless I’m in the sun, in which case I go with solarized light. I’m not entirely satisfied with solarized, but there aren’t a lot of good color schemes with both light and dark backgrounds. The color scheme I like the most and used before solarized was Tomorrow Night. I really liked it, but there are some problems with the Vim highlighting that I’m not entirely satisfied with, and Chris Kempson, the author, doesn’t seem to care about it anymore and never responds to pull requests (of which there are many) and issues. I still use a tomorrow-nightish theme on RefHeap because I can control it, but I don’t use it for my system anymore. If I had more time, I’d just fork it and work on it myself, but it’s quite a task. I sure wish somebody would though.

Also, iTunes. I consider music a part of my development environment. Yes, I know about the disdain for iTunes, the reason I use it over other media players is outside the scope of this blog post.

Hardware

I use a 2,2 macbook pro from ‘06 or ‘07. I did not pay a penny for this. The company I work for, Geni, gave me this laptop. It is old, but it still works really well and the hardware isn’t really ancient. It has 3GB RAM and a 2.33GHz intel core 2 duo. The only issues I have with it is that it is rather unsightly, has a DVI port, doesn’t have the newer and better multitouch trackpad, and is big and bulky.

My ideal hardware would be a new 13-15 inch macbook pro, but I think I’d be fine with a macbook air. In a pinch, I’d appreciate a middle class thinkpad loaded with arch linux. Unfortunately, I am not a man of means right now.

Conclusion

I am currently a Vim user recently converted from Emacs. If you’re new to Clojure and you like Vim more than Emacs or are already familiar with Vim, please ignore everybody who tells you that you need to use Emacs. You will be just fine with Vim. I chose Vim after two years of using Emacs, and I’ve yet to be dissatisfied. If you want to check out Emacs, by all means, do so. Having it under your belt and having more options is always good, but understand that it is absolutely not a necessity for Clojure.

If you’ve stumbled upon this blog post trying to find the best way to get started with Clojure, then you have found your answer. The answer is “whatever you are comfortable with”. Go install Leiningen and use it instead of trying to ‘install’ Clojure, and then use whatever editor you are familiar with. If you already like Emacs, use Emacs; if you like Vim, use Vim; even if you’d be more comfortable starting with an IDE, you are fine. Go get Counterclockwise for Eclipse or La Clojure for IDEA. If it begins to not be enough for you, check out the editors. There is no wrong answer here and no silver bullet. My friend Phil Hagelberg says it best: whatever you do, do not let your editor get in the way of you learning Clojure.

Thanks for reading.

1 This is a joke. Please take it as such. I don’t dislike Python. Python is our friend. Take a deep breath.

Thanks a lot to Andrew Brehaut for proof-reading and advising me a bit. He made me do this, so if anything I say here offends you, please direct all furious comments and bashing at his email address. Thank you.

Waving Our Tentacles

| Comments

Everybody knows that Github is fantastic. It is a wonderful service that not only hosts your Git repositories but also gives you a great platform for managing your projects and handling large-scale collaboration. It has arguably the best code review mechanism around (the pull request) as well as project wikis, issues, organizations, and even private repositories (on paid accounts) for the non-FOSS and business folk. It is an essential tool for the open source developer.

But we’re not really here to talk about Github as a service. We’re here to talk about Github’s new v3 API and my Clojure library, tentacles, that provides a Clojure interface to it.

While writing the library, I obviously had to test things as I went along. In doing this, I realized how elegant and powerful it is to work with APIs from Clojure if you have a simple and concise library for doing so. The Github API has some really neat things in it that are really fun to play with, even if we aren’t doing anything with them. This post is going to serve several purposes:

  1. We’re going to learn how to use Tentacles.
  2. We’re going to learn how to use some important parts of the Github API.
  3. We’re going to use the Clojure REPL as a prompt for interacting with the Github API — a very powerful concept.
  4. We’re going to get to see what Tentacles can do.

Note that I’ll be using two accounts in my examples: Raynes, my own account and amalloy, Alan Malloy’s account. It is about time he and I compete for world domination. Furthermore, I’m going to pretty-print some results with clojure.pprint.

Playing along

If you want to play along, go ahead and create a new project.

lein new tentacles-fun

Next, edit your project.clj file and add [tentacles "0.1.2"] to your :dependencies. After that, just run lein repl and have a blast.

Users

Tentacles supports the entire Github API, but we’re going to start with Github’s user api. It has some very interesting data that we can look at.

We can, of course, get information about a user.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
user> (require '[clojure.pprint :as pp])
nil
user> (require '[tentacles.users :as users])
nil
user> (pp/pprint (users/user "amalloy"))
{:followers 30,
 :following 9,
 :gravatar_id "1c6d7ce3810fd23f0823bf1df5103cd3",
 :name "Alan Malloy",
 :avatar_url
 "https://secure.gravatar.com/avatar/1c6d7ce3810fd23f0823bf1df5103cd3?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
 :bio nil,
 :location "Los Angeles, CA",
 :html_url "https://github.com/amalloy",
 :public_repos 56,
 :created_at "2010-08-18T16:37:15Z",
 :login "amalloy",
 :url "https://api.github.com/users/amalloy",
 :email nil,
 :type "User",
 :public_gists 160,
 :hireable false,
 :blog "http://hubpages.com/profile/amalloy",
 :id 368685,
 :company "Geni"}

You might note that Alan’s bio is nil. That’s because he has no life. Robot and all that.

Next, let’s learn a thing or two about ourselves. First, we’re going to need our authentication information quite a bit, so lets go ahead and def it so we don’t have to type our password 10 thousand times.

1
2
user> (def auth "Raynes:REDACTED")
#'user/auth

Truthfully, I just wanted to only have to do that once because I have a habit of forgetting to remove my password during demonstrations like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
user> (pp/pprint (users/me {:auth auth}))
{:disk_usage 46932,
 :collaborators 0,
 :plan
 {:private_repos 0, :collaborators 0, :space 307200, :name "free"},
 :followers 85,
 :following 36,
 :gravatar_id "54222b6321f0504e0a312c24e97adfc1",
 :name "Anthony Grimes",
 :avatar_url
 "https://secure.gravatar.com/avatar/54222b6321f0504e0a312c24e97adfc1?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
 :bio
 "My name is Anthony Grimes. I live in a small town called Eldridge in Alabama. I am a programmer and a very avid supporter of functional programming and Clojure. I am currently writing a book on Clojure called [Meet Clojure](http://meetclj.raynes.me). I'm the author (or co-author) of a number of Clojure projects including [Try Clojure](http://tryclj.com) and [clojail](https://github.com/flatland/clojail), having spoken about the latter at Clojure Conj 2011. I am currently employed by [Geni](http://geni.com) as a paid intern working with Clojure on the backend.",
 :location "USA, AL",
 :html_url "https://github.com/Raynes",
 :owned_private_repos 0,
 :public_repos 58,
 :created_at "2009-02-14T03:25:23Z",
 :private_gists 137,
 :login "Raynes",
 :url "https://api.github.com/users/Raynes",
 :email "i@raynes.me",
 :type "User",
 :public_gists 457,
 :total_private_repos 0,
 :hireable false,
 :blog "http://blog.raynes.me",
 :id 54435,
 :company "Geni"}
nil

As you can see, I definitely have a life.

So, what’s up with how we gave tentacles our authentication info? We passed it a map containing an :auth key. This is an idiom in tentacles. The Github API has a lot of API calls that can have required as well as optional arguments. Most of the POST api calls take a JSON hash of data (but not all of them). Tentacles represents this in a very simplistic way. Any API call that takes optional arguments or does something special when given auth info translates to a function whose last argument is an optional map. Any API call that requires authentication, regardless of whether or not it has optional arguments, must take an options map (even if it will only ever contain the auth info). Furthermore, any required arguments that an API call takes are required positional arguments to the equivalent tentacles function.

Okay, so I have this theory. I am pretty certain that I am much more popular than Alan. I’m nicer, arguably smarter, definitely better looking, and I certainly wear better clothes. Can the Github API tell me if I’m correct? You bet it can! The obvious and canonical measure of epeen size is follower count! Let’s tally ‘em up!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
user> (pp/pprint (users/followers "amalloy"))
[{:login "MayDaniel",
  :avatar_url
  "https://secure.gravatar.com/avatar/e917432c8e85f043647b2c57b443c56f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
  :url "https://api.github.com/users/MayDaniel",
  :gravatar_id "e917432c8e85f043647b2c57b443c56f",
  :id 188450}
 {:login "Raynes",
  :avatar_url
  "https://secure.gravatar.com/avatar/54222b6321f0504e0a312c24e97adfc1?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
  :url "https://api.github.com/users/Raynes",
  :gravatar_id "54222b6321f0504e0a312c24e97adfc1",
  :id 54435}
 {:login "tonyl",
  :avatar_url
  "https://secure.gravatar.com/avatar/43b2ca65e7a2cadf849adf103e6c066d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
  :url "https://api.github.com/users/tonyl",
  :gravatar_id "43b2ca65e7a2cadf849adf103e6c066d",
  :id 31147}
  ...]

Okay, so that isn’t very helpful. Github gives us very verbose information about followers and it gives us a lot of info. Let’s trim that down a bit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
user> (pp/pprint (map :login (users/followers "amalloy")))
("MayDaniel"
 "Raynes"
 "tonyl"
 "jColeChanged"
 "hoggarth"
 "ossareh"
 "stonegao"
 "ohpauleez"
 "raek"
 "segfaulthunter"
 "invaliduser"
 "gigasquid"
 "Clinteger"
 "odekopoon"
 "devn"
 "dbyrne"
 "imissmyjuno"
 "k4rtk"
 "xmlblog"
 "jeremyheiler"
 "amcnamara"
 "sconover"
 "srid"
 "mbacarella"
 "carlwarnick"
 "spoon16"
 "octopusgrabbus"
 "daviddavis"
 "andreisavu"
 "RafalBabinicz")
nil

That’s better. Now count them.

1
2
user> (count (users/followers "amalloy"))
30

Huh? That’s no good! He definitely has more followers than that. What’s going on here is that Github paginates results. By default, there are 30 items per page of results and the maximum number of results per page is 100. Let’s go ahead and set it to 100.

1
2
user> (count (users/followers "amalloy" {:per-page 100}))
30

Oh… He really does only have 30 followers. Well then. Moving on.

1
2
user> (count (users/followers "Raynes" {:per-page 100}))
85

I think I’ve won this one. It’s the hair that does it, I think. There is also a specialized call to get the currently authenticated user’s followers, so we could have used it instead:

1
2
user> (count (users/my-followers {:auth auth :per-page 100}))
85

Any way you skin it, I’m better looking than Alan. But who is the better person? Who is the most… outgoing? Let’s find out!

1
2
user> (count (users/following "amalloy" {:per-page 100}))
9

9… What about me?

1
2
user> (count (users/following "Raynes" {:per-page 100}))
36

This just isn’t looking good for ol’ Alan. That’s enough of that, before I hurt his feelings.

This isn’t all you can do with the user API. Check out the docs if you want to see the rest.

Repos

So far, we’ve found out that I am better looking than Alan, more popular, and that I am a better person. But that isn’t all that matters! Who is the most hardcore coder? Tentacles tentacles on the octocat, who of us two does not code trash?

Our first measure will be a repository count. If I have more repositories than he does, then obviously I love coding more than him. Github has a dedicated API call for getting the authenticated user’s repositories, but we don’t want to use that, since it would also list private repos. While I don’t actually have any of those, I don’t want to be accused of skewing these numbers. This is srs bsns! Nonetheless, tentacles has a function for that called repos, just in case you need it (for cheating).

1
2
3
4
user> (require '[tentacles.repos :as repos])
nil
user> (count (repos/user-repos "Raynes" {:per-page 100}))
58

Wow! I have 58 repositories! Let’s see how many of those are forks.

1
2
user> (count (filter :fork (repos/user-repos "Raynes" {:per-page 100})))
27

Wow! 27. I’m a forkaholic. Now for Alan.

1
2
user> (count (repos/user-repos "amalloy" {:per-page 100}))
56

Ooooooh, it’s close. It all comes down to the forks now.

1
2
user> (count (filter :fork (repos/user-repos "amalloy" {:per-page 100})))
38

HAH! Now, I’m not good at math, but I’m pretty sure that means I have more original repositories than he does. Cause that’s how I roll. Obviously, given these numbers, I love this craft waaaaaaay more than Alan does.

But who has the most popular code? I say we compare the number of watchers on our most popular projects.

1
2
user> (count (repos/watchers "4clojure" "4clojure" {:per-page 100}))
100

I highly doubt that that is an even 100. It probably just cut off at 100 because that’s our max. Let’s check the next page.

1
2
user> (count (repos/watchers "4clojure" "4clojure" {:per-page 100 :page 2}))
27

127 watchers! What about my biggest project?

1
2
user> (count (repos/watchers "flatland" "lazybot" {:per-page 100}))
53

Oh noes! Maybe that isn’t my biggest one.

1
2
user> (count (repos/watchers "Raynes" "tryclojure" {:per-page 100}))
57

._. I concede. He wins this one. Alan obviously has the most popular projects. You can’t win ‘em all.

Just for fun, let’s look at language stats:

1
2
3
4
5
6
user> (pp/pprint (repos/languages "Raynes" "tryclojure"))
{:Clojure 7419, :JavaScript 4471}
nil
user> (pp/pprint (repos/languages "4clojure" "4clojure"))
{:Shell 527, :Clojure 159307, :JavaScript 106110}
nil

We’ve both employed some tricks to make it so Github doesn’t think our projects are Javascript projects. I don’t store my JS dependencies in the repo and Alan puts them in a directory that Github doesn’t care about. We’re both clever, in any case.

This doesn’t even touch what the repo API is capable of. With Github’s v3 API, even download uploads are supported! Check out the full API in the marginalia docs

Issues

I wonder who has the worst code? I bet that if we check the number of issues on our top projects, we’ll be able to find this out.

1
2
user> (count (issues/issues "Raynes" "tryclojure" {:per-page 100}))
0

Bang! No open issues. ‘Cause that’s how I roll. Let’s check the closed ones as well.

1
2
user> (count (issues/issues "Raynes" "tryclojure" {:per-page 100 :state "closed"}))
20

So a total of 20 issues. What about 4Clojure?

1
2
user> (count (issues/issues "4clojure" "4clojure" {:per-page 100}))
29

Ahahaha! They’ve got more issues open than I have open and closed combined.

1
2
user> (count (issues/issues "4clojure" "4clojure" {:per-page 100 :state "closed"}))
100

Doesn’t even fit on one page!

1
2
user> (count (issues/issues "4clojure" "4clojure" {:per-page 100 :state "closed" :page 2}))
59

159 closed issues! Wow! That must be some terrible code. I feel sad for the little fellow.

As with the rest of our examples, this is only the tip of the iceberg. Check out the Marginalia docs for more.

Gists

Finally. One final competition. Gists. The way I see it, if I have more gists than Alan does, then I’m… uh… I’m just a damned better person. I don’t need a reason.

1
2
3
4
5
6
user> (require '[tentacles.gists :as gists])
nil
user> (count (gists/user-gists "amalloy" {:per-page 100}))
100
user> (count (gists/user-gists "amalloy" {:per-page 100 :page 2}))
60

160 gists. Not bad. I bet I can do better.

1
2
3
4
5
6
7
8
9
10
user> (count (gists/user-gists "Raynes" {:per-page 100}))
100
user> (count (gists/user-gists "Raynes" {:per-page 100 :page 2}))
100
user> (count (gists/user-gists "Raynes" {:per-page 100 :page 3}))
100
user> (count (gists/user-gists "Raynes" {:per-page 100 :page 4}))
100
user> (count (gists/user-gists "Raynes" {:per-page 100 :page 5}))
57

457 public gists! PUBLIC ONES! I am obviously, for reasons I am not certain of, the better person.

The Gist API is extensive and complete. It even includes a way to create gists now! Check out the rest in the Marginalia docs.

Conclusion

I’m better than Alan.

Real Conclusion

The Github API is awesome. Clojure is an awesome language for working with APIs. Working with APIs interactively is fun. Tentacles is fun. I like Tentacles. Tentacles is cool.

Thus concludes our demonstration. This post only just touches the capabilities of the Github v3 API. Tentacles supports all of it. Check out the Marginalia docs and the Github API docs for more awesome.

Finally, these numbers/stats are obviously meaningless, so don’t look into them too much. It’s all in good fun.

The Clojure Community and Me

| Comments

Origins

When I was around 13 years old, I played a game called Diablo II. You’ve probably heard of it or played it. It was a fun little RPG that had a huge community of hackers surrounding it. I would often visit the blizzhacker’s IRC channel and chat with the community of programmers, or just listen in awe as they talked about amazing things that made no sense to me and left me baffled at how anyone could understand it. One person in particular was a Haskell programmer. He was a very smart fellow that I looked up to and whose opinion I valued. Some of these people were C#, C, and even D programmers. This was my first introduction to programming.

I decided that this was something I was interested in and would like to do, so I spent the next couple of months beating my head against Python, C#, Boo, and a number of other languages that I probably played with and simply don’t remember. Nothing really made much sense during that time. Python was the closest I got to things clicking. I had a lot of time to do these things because I’ve always been home-schooled.

I always say that Haskell was my first language. That is not entirely true. I played with many languages in the beginning. Haskell was, however, my first real introduction to programming. It was the first language that made sense. It was through Haskell that I was able to make sense of programming as a whole, including Object Oriented programming.

A lot of people wonder if learning Haskell, a purely functional language, as a first language would make OOP languages be as difficult to learn and understand as functional languages are to OOP developers. My answer, given my experiences, is no. Learning a functional language first gave me the programming foundations that I needed to understand OOP and how it compared to other paradigms. Basically, Haskell told me “Hey, this is programming. This is what it means and this is what you do.” and then Object Orientation was just another layer on top of that. Another way of doing things. Programming is simple, but OOP clouds that and makes it look unnecessarily complex. If I had to teach someone to program, I think I’d start with a functional language given my experiences.

Enter Clojure

So what comes after Haskell? After I had used Haskell for a couple of months and had got a few projects under my belt, it was time for a new step. I felt that my next logical step was a Lisp. Clojure was new and getting a lot of attention. It was very practical, had an amazing set of minds behind it, and a very welcoming tight-knit community.

I didn’t do a whole lot with Clojure at first. I spent a lot of time just learning the language and not actually doing anything. My first serious Clojure project was lazybot (originally known as sexpbot), an extensible IRC bot. It was a great project that I still use and actively maintain.

Originally, lazybot was a Pircbot. While Pircbot is an excellent Java library and is easy enough to use from Clojure, I really wanted to have a Clojure IRC library to use for it. That was my next project, Irclj. Irclj is an asynchronous (a word that I didn’t understand at the time of writing it) IRC protocol library that I am currently in the process of rewriting. Nonetheless, it was my first introduction to lower-level network programming and the first time I’d ever done anything with any internet protocol. You can find lazybot in its current incarnation in the #clojure IRC channel where he provides services such as Clojure and Haskell code evaluation.

That project was my gateway into the world of serious programming. I spent a lot of the next year working on lazybot and writing plugins for it. I had some other projects here and there, but lazybot was the one that mattered the most to me.

Things People Enjoy

If I’m known for anything at this point, then I’m known for Try Clojure. It is a website that, like TryRuby, is designed to introduce people to the Clojure language very quickly by providing an interactive tutorial and an in-browser REPL that evaluates code on the server side. This was accomplished originally using Heinz N. Gies’s clj-sandbox Clojure sandboxing library and eventually one that my best friend Alan Malloy and I wrote later, called Clojail.

How To Get Famous

Clojure Conj 2010 brought a lot of firsts for me. It was my first trip outside of the state of Alabama where I was born, raised, and still live; my first time flying in an airplane; my first conference; and the first time that I felt that I was a real member of a community. It was, in general, a huge leap in my life. The last two years have seen me grow the courage to consider myself a ‘real’ programmer, and begin programming professionally.

But it wasn’t really just the conference that did these things for me. It was the months leading up to the conference.

I wasn’t going. I was 16 and I didn’t have a job. My family is not particularly poor, but with the bulk of our income coming from disability checks, conferences were just not really something that could ever possibly happen. But I was okay. I mean, I was sad that I’d miss such a huge event, but I never expected to be able to go in the first place so the realization that it wasn’t happening was easy to take.

I’m not sure exactly how it happened, but I think somebody in the #clojure IRC channel asked me if I was going to the conference. Either that or I mentioned it for some reason. Chas Emerick happened to be watching. He immediately messaged me privately and asked me why I wasn’t going to be able to make it. I told him that I simply did not have the funds to travel to North Carolina, pay for lodging, and register at the conference. Furthermore, it wouldn’t be just me — my mother would need to travel with me (for obvious reasons). He said, in so many words, “well, let’s see what we can do”.

Not much time passed before Chas told me Relevance had happily agreed to cover my stay at the hotel and waive the conference registration fee. I was floored. Chas decided that the best way to get the rest of the funds for air travel and miscellaneous travel expenses would be to hold a fund-raiser. He wrote a blog post, set the goal for $1000, and threw up a paypal donate button. And so it began.

Oh how the twitterverse rooted for Anthony Grimes on that day. Hacker News, Reddit, IRC. Even people outside of the Clojure community itself were donating for my cause. A whopping 72 minutes later, our goal had been reached (and slightly exceeded). 72 minutes is what it took for the Clojure community and others to raise $1000 for a 16 year old kid to be able to attend his first conference. Chas bought my mother and I our plane tickets and I was on my way.

This would spark what is now becoming a tradition. For this last conference, Chas Emerick once again took it upon himself to help somebody get to the conference. Ambrose Bonnaire-Sergeant had to travel much farther than me and thus his expenses were much greater. The Clojure community once again rose to the task and met the goal.

Clojure Conj 2010

Oh wow. What a whirlwind. I honestly only remember the very best parts of the whole trip. It’s all just a big bright and colorful blur.

I arrived at the hotel and walked into the lobby. How appropriate was it that the first person I met and talked to was Chas Emerick, sitting right there in the lobby with his laptop as if he were waiting on me. I resisted the urge to hug and kiss him and instead opted to shake his hand.

When I checked in to get my room key, the woman at the counter said, and I quote, “It’s about time! Everybody has been asking if you had arrived.”. That certainly blew my mind.

The next two people I met, also appropriately, were Lance Bradley and Justin Balthrop, two of my very best friends and people who would eventually be my co-workers. I didn’t even get to sit down once I got to the room, they already had me walking with them to a restaurant. We had fun that night.

The next day was even crazier than the last. Everyone who saw me wanted to shake my hand and talk to me. People would ask me about my experiences and praise me for my projects. I felt so much like a celebrity. Even Rich Hickey himself would speak to me and shake my hand later on.

The conference was wonderful. The talks were great, but the social aspect of it is what truly made it the most important experience of my life. Meeting everybody for the first time. The energy that emanated from everyone pulsed so hard that it could almost make your teeth rattle.

2011

The next year was a blast for me. A few months after the conference, I was hired as an intern at Geni, working remotely under Justin Balthrop and Lance Bradley, two close friends, on the site’s backend with Clojure. With Clojure! My first job is developing Clojure! Winning! I quickly learned that making money is wonderful and that Macbook Pros are the best things since sliced bread.

At about the same time I got my job, I also landed a book deal with No Starch Press. I’m currently writing a book called Meet Clojure for them.

Clojure Conj 2011

The moment Clojure Conj 2011 was announced, I was plotting my way there. Clojure conferences are wildly addictive. Worse than heroin. But hey, I was making some money now. But hey, this conference is going to cost even more than the last. But hey, maybe Geni will pay for some of it? But hey, I’m 17, so liability is a big complicated legal bitch. Mostly, I knew I would get there some how, but I hadn’t quite worked out exactly how. If I had to, I would just save my paychecks for a month or so and not spend very much at all. This would have worked out, since I still live at home and have the privilege of being fed by a lovely woman with excellent shopping and frying pan foo. But hey, it didn’t have to work out.

Speaking

I vowed that I would not submit a talk for Clojure Conj 2011. I was utterly certain that I would not be able to perform a 40 minute long presentation in front of the entire Clojure community and be able to keep them interested while doing it.

But damn them all to hell, Justin, Lance, and Alan decided that they would submit talks. Every single Clojure person at Geni was submitting a talk except for me. I conceded, assuming that there would be no earthly chance of my talk getting chosen, and submitted a talk about JVM sandboxing and Clojail.

So, my talk got accepted. As soon as I cleaned out my undergarments and finished receiving congratulations from my friends, I went and cleaned them out once more. This was great though. It meant that Relevance would pay for my room (which also meant my mother’s room), waive the conference registration fee, and even give me a travel stipend (once I arrived) that would cover my own plane ticket. That dropped the total costs of the conference (disregarding miscellaneous expenses) to around $250. Winning!

Actually Doing It

But shit, now I have to compose and perform a talk. For 40 minutes. In front of Rich Hickey and everyone else that I am intimidated by and who is exceedingly smarter than I am.

So, I did what any person this terrified would do. I forgot it happened and waited until about two months before the conference before I even thought about writing the talk. I ended up doing the majority of it over about two weeks because Justin had given me the ultimatum that I would either practice it live with my co-workers over Skype or not get paid. ;)

It went surprisingly well over Skype. They gave me insanely awesome feedback and a lot of encouragement. The Clojail talk was the product of not only my blood sweat and tears, but those guys as well. That they convinced and (half-serious) forced me to practice the talk was the best thing that could happen to me. It showed me how nervous I would be at the Conj and taught me how to control it.

The Conference

I was once again greeted with a healthy round of handshakes after my arrival at the venue. Early registration was great. I met Carin Meier, a person whom I had worked with on 4Clojure. A handshake would not do for her, no, she wanted a hug. That was when I really felt that things would be okay and that, regardless of what happened with my talk, everything would work out in the end.

And it did. After meeting my best friend in person for the first time, Alan Malloy; after Carin Meier’s big ol’ bear hug; after letting the atmosphere of Clojure Conj 2011 and the Clojure community once again sink in and take hold of me, I felt so good that I didn’t bother practicing my talk again before I performed it. I was okay.

My talk went great. It was well received and people praised me for it for the remainder of the conference. Either immediately after or during my talk, Rich Hickey tweeted (a rare occurrence) the following: “@IORayne is awesome, killer job on library and talk! #clojure_conj”. And if that wasn’t enough to make me piss myself in glee, he approached me right after my talk, shook my hand, and said the equivalent in person. This man, the public speaker of the decade, praised me on my speaking abilities. Holy. Shit.

After that, I did a brief interview with Chas for his podcast Mostly Lazy, and a slightly longer interview with Runtime Expectations of Codebass radio. Both should be made public soon.

Oh man, Clojure Conj 2011. I’ve never attended a non-Clojure Conj conference before, but surely this is as good as it gets, right? I can not think of a single thing that I did not like about the whole experience. Relevance knows how to put on a conference.

Conclusion

I’m not really sure why I wrote this. I suppose I did it for two reasons:

  1. At least 10 thousand people asked me about my origins at the Conj. Wondering how I got into programming and such.
  2. I can not say enough good things about the Clojure community. Sometimes I just need to tell people about it, and I can’t think of a better way to do that than by pointing out that my entire life has been built around it.

So, that’s me. Where I came from, what I’ve done, and more importantly, what the Clojure community has done for me. I owe so much to all of you that I can’t really express my thanks in words. Instead, I hope that my contributions to the world will be enough. My motivation is to make you proud.

Future

It’s nice to have one of these.

I don’t really know what the future will hold. At the very least, more projects will always be forthcoming. I want to make nice things. Furthermore, I do currently have a job, albeit an internship (a paid one), with Geni. I’d like to work with them full time at some point after I turn 18 and graduate high school. This would obviously involve extended stays in California and most likely a move, even if not immediately. That’s all some pretty serious stuff that I nor my co-workers are taking lightly. They are very supportive of me to the point that they allow me to work remotely, even though I am the only one who does so on a regular basis. This means that they have to actively put effort forth to keep me in the loop about things, since I’m not there to hear their conversations. I’ve never once saw them complain about it.

So, I think my future is bright. I’m happy that I’m busy and I have a lot of great things ahead of me. I look forward to the future and whatever it may bring.

Thanks for reading.

-Anthony

P.S. Many thanks to Dominik Picheta and Ricky Elrod for reading this for me and making sure I’m not insane.

Moving Try Clojure to Heroku

| Comments

tl;dr: At first I was like “uhh…” but then I was like “AH!”.

I started playing with Heroku a bit recently. I had heard all sorts of wonderful things about it and figured it was worth giving a go. I never expected to get anything done because I wasn’t willing to put a lot of effort into it, since I was planning on just playing around with things.

So, my plan was to see if I could get Try Clojure running on Heroku. I took a seat and began reading documentation. Well, if a two minute blog post is documentation. The funny thing is, it wasn’t until I actually decided to move it to Heroku permenantly that I actually had to read official Heroku documentation, and that was only to find out how to get my domain pointed at the Heroku instance and to find out more info about how much the site would be able to handle on the free plan.

It took me all of 10 minutes to get Try Clojure running on Heroku. The only reason it took that long was because I didn’t know that I had to start my server on a port that Heroku sets the environment variable PORT to. So, about 8 of those 10 minutes were me committing a fix for that. It was less a less than 5 line change.

I had to modify its project.clj file to add a :jvm-opts line to set the Java policy file for the application, but that was only because cake reads jvm options from .cake/config and Leiningen takes a key in project.clj for them. At this point in time, Heroku only supports Leiningen on the Clojure stack. I’ve been told that cake is not out of the question in the future. It doesn’t really matter because it was a good idea to add :jvm-opts to my project.clj so that I could maintain complete Leiningen compatibility in Try Clojure. I have absolutely nothing against Heroku for not supporting cake – it simply isn’t a big deal, since Leiningen and cake have mostly compatible project descriptions and Try Clojure’s project file is very simple.

Finally, I had to create a Procfile containing the following:

web: lein run

and this tells Heroku how to run my code.

After my code was set up, all I had to do was sudo gem install heroku and then heroku create --stack cedar and bang, my project was a Heroku project. To deploy, I simply ran git push heroku master, which pushed my code to the heroku remote that heroku set up when I ran the create task. The code was pushed, it ran my code with lein run, shot me a link to the app, and tada – Try Clojure runs on Heroku.

I was completely floored by how easy all of this was. And that’s how easy it always is. When I want to deploy, I just push my code to the heroku remote with git and Heroku handles the restarting and everything with absolutely no work on my part at all. This workflow won me over immediately.

So great, I have Try Clojure running on Heroku. Just an experiment and it worked really well. At this point, I had no intention of moving to Heroku permenantly. I didn’t know much about Heroku and how much the free account would give me.

I mentioned that it was running on Heroku on Twitter (and probably in the #clojure IRC channel as well, but I don’t quite remember). The next day, technomancy (Phil Hagelburg) asked me in the IRC channel if the main Try Clojure instance was running on Heroku, and I told him the equivalent of “Hell no, I don’t know anything about Heroku and I only have a free account. I don’t trust Heroku enough to move it over.”. It struck me as odd when he replied with “Heh” followed by a cute joke, but it didn’t dawn on me why he did it.

The next day, I remembered that technomancy had just recently started working at Heroku himself! One of our very own popular Clojurians! I ended up talking with him (he kindly approached me, offering to help) later that day. I read a lot of documentation around the same time and asked him a few questions.

What confused me the most was the concept of a ‘dyno’. This is a process of any type running on Heroku. Processes for stuff like Mongrel or Resque and, of course, your app and its own processes. In my case, I have one web process, which is what I defined in my Procfile.

Heroku takes a time-based approach to its services and billing. The idea is that you pay for how many hours each dyno that you use has run in a given month, and every free account has 750 free dyno hours. If I only run one dyno all month, I don’t have to pay anything at all. And even if an app that I use was to get slashdotted or something similar that would generate massive amounts of traffic, all I’d have to do is run a command or two to scale things up. I could add a dyno or two and only run them for as long as the traffic was too hard for a single dyno to handle the traffic, then I could scale it back down and I’d hardly have to pay anything at all unless I used those dynos for quite a while. You only pay for what you use, and you aren’t obligated to use anything more than what you need/want!

This all made me feel much better about the whole thing. Try Clojure is a fairly simple site that doesn’t get tons of traffic, so I decided I’d go ahead and move the main instance to Heroku. I even bought a new domain, tryclj.com to celebrate the move.

Try Clojure is now running entirely on Heroku, and I’m really enjoying it. I haven’t had to scale things up at all at this point, even though it got pounded with traffic when Heroku tweeted about the move. I kept an eye on it during that time and it never even slowed down.

Really, what won me over is the workflow. It is soooo easy. I mean, deployments by pushing to a git remote? That’s just beautiful. I can make changes and deploy them faster than a Github employee! Finally, the fact that Phil was so eager to help me really says something about Heroku in my book. If they hire people like him, I bet the rest of their team is equally as lovely.

I look forward to a long and fruitful future with Heroku, and I thank them for their fantastic service and giving me a reason to not have to host and maintain that site on my own VPS.

Try Clojure’s source code is on Github. Check it out if you’re interested in seeing a simple website that runs on Clojure, the excellent Noir web framework, and Heroku.