Hello!

Sometime around 2 and a half months ago, I started to work on a new project 
using Clojure. I've been using Python heavily for about 6 six years working 
for a small direct mail company and before that started programming with 
Ruby on Rails. This new project was something out of left field, so I had 
different options on what technology to use. I ended up choosing Clojure, 
and my work on the site has been my first real experience using a lisp, 
Clojure, and the JVM. I'd like to share my experiences and how that has 
differed with my previous Python work.

Before that, I'd like to make a little plug for my site. It is called 
kodefund <http://www.kodefund.com> (www.kodefund.com). The basic idea is to 
take the familiar Kickstarter model but to really focus on applying that to 
open source development. I feel that previous crowdfunding efforts have 
shown that there is an interest by developers to fund projects that they 
are enthusiastic about. When this works, everyone wins: the developer 
working on the project can devote their full time and effort on the actual 
project and still make a living and others get the benefits of the open 
source software. I feel like it is preferable over selling licenses to 
proprietary software or other efforts.

So, every project on kodefund is required to be open source. This 
differentiates it from other crowdfunding sites, and helps to apply a 
filter: you know what you are getting when you go there instead of seeing 
dozens of projects for unrelated stuff. 

One other difference is that you can also start a project which is more or 
less a "reverse" Kickstarter. This allows you to take an idea for a project 
or issue you want fixed, raise funding, and find someone who will actually 
implement the project. Other users get to submit "applications" and you 
choose from them to find the most capable candidate. Once you chose an 
application, that person takes over the project.

Finally, one other push I want to make is to open up proprietary software. 
Maybe your company has written some software in-house, but there's no real 
incentive to release it. What if you could crowdfund the software, get paid 
to release it, and the open source community as a whole could benefit from 
that? 

I feel like crowdfunding and open source software are an ideal fit.

I'm getting off track here. I'll shift to my actual experiences using 
Clojure. I was more than a little nervous about using the JVM. It always 
seemed like some huge, scary thing, and digging into Java libraries was not 
something I wanted to do. Something which resolved this was leiningen. I 
feel like it is absolutely brilliant, and it really makes adding libraries 
to your project a non-issue. Things have slowly changed in Python, but it 
used to be that downloading dependencies was a global process and you ended 
up with a site-packages that was full of dozens of old libraries that you 
used for other projects. Being able to specify in my project.clj file 
exactly which libraries I need and those getting downloaded automatically 
is a really nice feature that I will look for similar functionality in 
other languages from now on.

I was also pleasantly surprised by the library availability. The vast 
majority of things that I needed such as oauth2 support and such already 
have decent Clojure wrappers. When I did drop down into Java, I found that 
to be painless. The JVM really does have a wide swath of functionality 
already available. Some of the things that I ended up using were email 
libraries, date formatting libraries, and an rss feed generator. There 
never was a point where I felt like I was going to have to just roll things 
by hand. Most of the hard work has been done.

Considering the language itself, one of the first things I noticed (or 
didn't) was the parentheses. I don't remember when, but they simply are a 
non-issue after a short amount of time. One slight thing I did have a 
problem with was that inserting a parenthesis at the wrong place could 
completely alter the flow of code and it was not immediately obvious. This 
is not an issue when you are closing off a line or two of expressions, but 
when you are halfway down the page, insert a paren and everything breaks, 
it could get frustrating. This is probably resolved through better editor 
usage. I unfortunately could never get emacs with clojure-mode and goodies 
working properly on my Windows machine, so I ended up using the 
counterclockwise Eclipse plugin. It was not a horrible experience but 
things such as auto-indenting a large block of code was something I never 
figured out.

Continuing on the surface, some of my favorite parts of the language are 
little syntax additions. I absolutely love the syntax for anonymous 
functions. Python obviously has limitations with lamdas anyway, but in 
Clojure, having a block of code like: (do (println test) (+ 3 3)) and being 
able to instantly convert that to an anonymous function by sticking a # on 
the front is really nice. Not having to explicitly name function arguments 
helps as well.

Destructuring syntax is amazing. Being able to break a map or a vector down 
and bind numerous variables in a let or function is something that simply 
is not easily done in Python without some magic. It was nice to have a 
function definition of something like (defn index [request] ...) in a view 
and to be able to grab relevant needed variables using the {:keys ...} 
syntax.

The language is full of these little bits that are really convenient, and I 
was constantly surprised by something new which significantly reduced the 
amount of code I was writing.  Having used it, it is straight up painful in 
my opinion to write markup in anything else. The -> operator, hash maps as 
functions, etc.

One thing which surprised my was the macros. Initially I didn't use a 
single macro in my code, and I really couldn't figure out why the were so 
lauded and considered important by lots of lisp developers. That changed 
later in the project when I noticed a familiar pattern in my code. The 
basic problem was that pretty much every single web request has a familiar 
flow:

Does the resource exist? If not, throw a 404.
Does the user have the proper permissions to access the resource? If not, 
redirect to login or throw up a permission denied page.
Is this a post? If not, render a form.
If it is and the post is valid, do some work and redirect. If not valid, 
render the form.

This got used over and over. In Django you often see this in the form of:

def index(request):
    item = get_object_or_404(...)
    form = Form(request, item)
    if request.method == 'POST' and form.valid():
        do stuff
        redirect()
    render('index.html', dict(form=form))

This isn't the worst thing in the world, but its just extra code that gets 
in the way of the literal intent of the code. When I noticed this pattern I 
ended up writing a macro which handled the resource check, the auth check, 
the validation check, the redirection, etc, for me. Once I got to this 
point, I really "got" macros and their power. You simply don't have the 
ability to implement your own flow control this easily in Python.

Now, to thinking and working functionally. Python is imperative in parts. 
One of my favorite parts in it is the list comprehensions, which can be 
very functional. But for loops and destructive updates abound. Coding 
without for and accumulators was maybe the most difficult adjustment for 
me. However, once I started using map (with the aforementioned excellent 
anon function syntax), I started wanting to use it everywhere I could, 
because the concept was so simple. The same goes for reduce. Much of the 
pain of lacking destructive updates is mitigated with things like 
update-in, and such. 

I guess for me the real question is whether programming functionally 
actually reduces the number of errors as some functional advocates put 
forward. The problem is that it is so damn hard to objectively compare the 
two. Did I have more errors when I was programming in Python compared to 
Clojure? I'd say most of my errors actually came from unfamiliarity of 
libraries or functionality. The idea that errors can be reduced is 
interesting, but I'm not ready to fully commit to that suggestion unless we 
really see hard data. I do know that there are places where destructive 
updates would be convenient, but I can appreciate basis of programming 
functionally.

Was there anything I missed when using Clojure compared to Python? The 
libraries seem to be a wash, the languages themselves are comparable. If 
anything I did want maturity in some of the libraries. For example, noir 
has an excellent error validation library. However, compared to Python 
libraries which do validation and conversion, I found myself writing and 
debugging extra functionality that I had to implement. I found myself 
digging around in github repos to actual read code instead of documentation 
a lot more than I ever did with Python. Obviously these are just issues of 
time, and they'll improve. Clojure docs and the cheatsheet help a lot, 
though.

Stacktraces can take a while to get used to, and some of the error messages 
are cryptic. I can't say how many hours I spent figuring out why #([:key 
"test"]) wasn't working (you can't place a vector literal directly inside 
an anonymous function like this. Maybe that should have been obvious to me, 
but once I ran across these issues and understood them, the pain of 
understanding stacktraces was mitigated by a large margin.

I guess if there is anything I'd love to see is some kind of style guide. 
Python has the PEP8 style guide, which more or less suggests how code 
should be written, not that it has to be written that way. There were lots 
of times I found myself wondering whether the "right" way was to indent the 
if form after the conditional or first argument, or whether it was 
considered "bad" form to nest multiple lets, and how that should be 
handled. The current cheat sheet is similar, but its not very prescriptive. 
I'd love to see something which suggests how common tasks should be done, I 
feel like it might help newbies like me feel more at ease. Does such a 
thing like PEP 8 exist for Clojure?

Well, those are some of my notes on using Clojure. I feel a little 
embarrassed writing this up because I feel like someone will pick it to 
death, and I'm wish I could delve further into hard details instead of 
dwelling so much on little syntax differences. It has been a fun, useful 
learning experience, anyway. I feel like anyone who has not worked with a 
lisp or a functional programming language owes it to their own development 
to work with Clojure, it really does help you to understand the whats and 
whys of the JVM, macros, and functional programming.

I'd especially love to see, kodefund, used by the Clojure community. I feel 
like it is a great way to get new libraries off the ground, or to find 
people to fix bugs, or even to open up previously  closed software.

If there was a project that you were considering putting on Kickstarter or 
one of the other crowdfunding sites, please consider kodefund. Unlike the 
bigger sites, you will have my full attention to your project, and I'm more 
than willing to work with you to improve and change parts of the site which 
make crowdfunding more suitable to open source projects.

I've worked really hard to make things as simple as possible. You can start 
or fund a project no matter where you live, all that is needed to make a 
pledge is a credit card, and github, twitter, facebook, google are all 
supported to sign up. Give it a try, let me know what you think. I've tried 
to explain the rationale further here: http://www.kodefund.com/about/

So, if you've got any questions about kodefund <http://www.kodefund.com> or 
Python/Clojure, I'm happy to answer them. Thanks to those who have spent 
their time making this such a useful language!

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to