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