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.
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:
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:
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:
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:
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:
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.
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:
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.
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.
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:
Now, let’s write a function to extract the number of lines from the json.
123456
getRHLines::String->IntegergetRHLinesjson=caseHM.lookup"lines"hmofJust(Number(In))->nNothing->error"Y U NO HAS NUMBER?"where(Just(Objecthm))=decode(BS.packjson)::MaybeValue
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.
{-# LANGUAGE OverloadedStrings #-}moduleBlahwhereimportData.Aeson((.:),(.:?),decode,FromJSON(..),Value(..))importControl.Applicative((<$>),(<*>))importData.Time.Format(parseTime)importData.Time.Clock(UTCTime)importSystem.Locale(defaultTimeLocale)importControl.Monad(liftM)importData.Attoparsec.Number(Number(..))importqualifiedData.HashMap.StrictasHMimportqualifiedData.ByteString.Lazy.Char8asBSparseRHTime::String->MaybeUTCTimeparseRHTime=parseTimedefaultTimeLocale"%FT%X%QZ"dataPaste=Paste{getLines::Integer,getDate::MaybeUTCTime,getID::String,getLanguage::String,getPrivate::Bool,getURL::String,getUser::MaybeString,getBody::String}deriving(Show)instanceFromJSONPastewhereparseJSON(Objectv)=Paste<$>(v.:"lines")<*>liftMparseRHTime(v.:"date")<*>(v.:"paste-id")<*>(v.:"language")<*>(v.:"private")<*>(v.:"url")<*>(v.:?"user")<*>(v.:"contents")getRHLines::String->IntegergetRHLinesjson=caseHM.lookup"lines"hmofJust(Number(In))->nNothing->error"Y U NO HAS NUMBER?"where(Just(Objecthm))=decode(BS.packjson)::MaybeValue
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.
!!! 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.
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.
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.
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.
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:
1234
(defnfoo[](let[x](yx)(zx)))
What happens if we want to take the let out of this code?
1234
(defnfoo[](yx)(zx))
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(.
1234
(defnfoo[](yx)(zx))
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.
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:
We’re going to learn how to use Tentacles.
We’re going to learn how to use some important parts of the Github API.
We’re going to use the Clojure REPL as a prompt for interacting with the Github API – a very powerful concept.
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.
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.
12
user>(defauth"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.
user>(pp/pprint(users/me{:authauth})){:disk_usage46932,:collaborators0,:plan{:private_repos0, :collaborators0, :space307200, :name"free"},:followers85,:following36,: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_repos0,:public_repos58,:created_at"2009-02-14T03:25:23Z",:private_gists137,:login"Raynes",:url"https://api.github.com/users/Raynes",:email"i@raynes.me",:type"User",:public_gists457,:total_private_repos0,:hireablefalse,:blog"http://blog.raynes.me",:id54435,: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!
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.
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:
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).
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.
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
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.
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.
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:
At least 10 thousand people asked me about my origins at the Conj. Wondering how I got into programming and such.
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.
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.
There is a fix-all solution to any problems you’re having with Clojure + Homebrew.
1
$ brew uninstall clojure
Followed by
1
$ brew install cake
Or
1
$ brew install leiningen
In all seriousness, if you’ve installed Clojure via any package manager and you’re having problems, that’s because it doesn’t make any sense whatsoever to install Clojure through a package manager. The JVM ecosystem just doesn’t work that way. Clojure is essentially a library – it’s stored in a jar.
Instead, you want to install a build tool. Cake or Leiningen are Clojure build tools. They are your ‘interface’ to Clojure. They handle all the project management, classpath management, REPL management, compilation, and everything else that you shouldn’t need to or try to do on your own.
Do not try to ‘install’ Clojure. Install a build tool instead. It’ll prevent 98% of all beginner issues related to classpaths and make it easier for people in the Clojure mailing list and IRC channel to help you with real problems. Furthermore, they make it really easy to manage everything from small scripts to large projects, and can even give you properly classpathed repls as easy as cake repl and lein repl.