Here are a few things I've noticed when I've (attempted to) show Clojure to others. I'm not saying that my sample (n=4) is representative, so if you think that is too small a sample size, there's no point reading further. I sat down at the computer to demonstrate to two, and had lengthy discussions with the other two.
1. (Not important) The name is unusual, and they've never heard of it. When I tell them that it runs on the JVM, you have access to all Java libraries, and that there is a large, helpful community with four - soon to be five - books published by major publishers, they view it as credible. Outstanding libraries written in Clojure, like Incanter, also help.
2. (Critical) After they realize it's not a toy language, the next question is ease of use. I was surprised that ease of use has nothing to do with the language itself. How can I make an executable that I can share with others? How can I access existing libraries? And it has to be something automatic, where you write the code, make the executable, and then you can run it by clicking the mouse or issuing a simple command.
This is where Clojure fails, big time. The claim is made that you don't need to know Java to use Clojure. That's false. You need a lot of knowledge of the Java build system, how to set the classpath, etc. True, you don't need to know much about Java the language, but you need to know a lot about Java the development environment. And you're not likely to learn much about it from the Clojure community, unfortunately, because it's expected you can learn it yourself. This is a big burden to impose on someone who wants to learn Clojure.
Counterclockwise helps a lot. It's dead simple to get started with a feature-filled Eclipse development environment. Got some Java libraries you want to access? Click a couple times to add them to your project. Want to use infix notation and a random number generator? Add the Incanter .jar executable in a couple clicks. Don't want to mess with the classpath? You don't have to.
Unfortunately I still haven't got the whole making a .jar figured out myself. There's still a long way to go in this area. Clojure has to free itself from the Java approach or it's only going to appeal to Enterprise Java developers looking for a good Lisp. The requirement that you understand and accept the Java approach was, to be honest, a dealbreaker. None of the four had much experience with Java (mostly by choice) and they were not interested in learning a whole new approach to software development plus Java.
3. (Sort of important) The parenthesis issue is really a non-issue. Whitespace is actually a bigger deal in Clojure than in Python. There's just so dang much indentation, and indentation is syntax, and there are so many levels of indentation in both directions in a single block of code.
4. (Very important) The typical approach to writing in any Lisp is to do a lot of nesting. "let" helps, but all the indentation I referred to above is due to nesting. You have to follow everything in a given line plus everything in indented lines below it to know what's going on. You don't usually see something like that in imperative code. Another thing is that using operators in prefix form is stupid. "+" is an infix operator. It should be possible to make infix operators the default.
5. (Hard to classify) They don't understand the importance of functional programming.
6. (Important) They like the idea of a customizable programming language. They customize everything else in their lives, so they were very open to the idea that you can customize your language. I think everyone would like to change something in their current language, so macros have appeal.
The most important thing I took away is that their evaluation of Clojure had almost nothing to do with the language itself, beyond the concept of macros, which they liked but didn't really understand. I think it's important to explain before you even start why the syntax is "funny". There's no reason to hide macros, they are a killer feature.
I realized that most of the world doesn't care all that much about programming languages. They are not interested in learning about new programming concepts, and if they've never thought about the basics of functional programming, they're not going to care if a new language supports it.
It's also obvious why Python is popular. If you like imperative programming, and you don't want to customize your language, Python can probably make you happy. I don't see Clojure having the same broad appeal any time soon.
One of the reasons that Python is popular is that it's easy read. One of the things that make it easy to read is that its small. With a large language, people tend to write in the subset they are comfortable with - their own dialect, as it were. Reading code written in someone else's dialect then becomes hard work.
ReplyDeleteCustomizing a language with macros is really cool - it lets you create your own dialect. But unike dialects in large languages, you can't check the language manual when you're reading someone else's dialect. You have to chase down and understand their macros. This is why the conventional wisdom in LISP languages is to only write macros if you can't write a function to do the job.
My approach is to use macros that are short, and give them the same documentation that I give to functions.
ReplyDeleteI agree that you should avoid creating your own dialect of the language, due to the readability factor that you mention, but also because then you're maintaining your own language.
When you want them, though, you're really happy you're using Clojure or whatever language has them.
On point 4 - have you tried out the -> macro? Also, how do you express (+ 1 2 3) in infix notation?
ReplyDeleteMaybe I'm alone on this one, but I find Counterclockwise despairingly slow. So I switched to Emacs, which made me discover its Paredit component.
It's really the bee's knees. You get to edit and traverse your code syntactically rather than typographically. A huge productivity boost that is only possible thanks to lisps' homocoinicity.
I use the -> macro from time to time. The problem is that in most languages you have 1 + 2 + 3 + 4, with the infix library in Incanter, you use ($= 1 + 2 + 3 + 4).
ReplyDeleteThat's not too bad, but since you'd never bind + to a piece of data anyway, the question arises why you can't set a global variable and use (1 + 2 + 3 + 4) without always adding the $=.
It just looks funny to write (+ 1 2 3 4) because mathematically + is an infix operator. You could use the threading macro as (-> 1 (+ 2) (+ 3) (+ 4)) but that too is a bit awkward.
I don't remember Counterclockwise speed problems. I've always used Eclipse for Clojure because I like Eclipse. I blogged a while back about my not so positive experiences trying to set up Emacs for a Clojure experimenter (one of the four this post is about).
Mathematical purity aside, I find 1 + 2 + 3 + 4 worse because you need to type 3 chars (" + ") for separating operands rather than just a single space, resulting in somewhat cluttered expressions.
ReplyDeleteThe lack of need for commas is nice too.
As logical operations come into place, benefits become even more evident. It just takes some time to get used to prefix notation.
Same for Emacs - I neither had a good experience on the first try but it's worth the 'pain' (which is very little actually).
I love IDEs but even thinking of *really* customizing their behavior is pretty scary - how many Eclipse users have ever developed/modified a plugin?
With Emacs it's the most natural, quick-and-dirty (in a good way) thing in the world - code-as-data at its best.
Take a look at this page. It creates a toy Clojure project using Leiningen. It begins with installing Clojure and ends with producing a Jar file. I found it to be very helpful in understanding "flow".
ReplyDeleteI think the hardest part for me is trying to force myself to write functionally. There is a natural instinct to write loopy-imperative code. When I have talked to other people about Clojure, the reluctance to change mindset is the biggest obstacle. Personally, I enjoy the challenge to the point where I grimace writing imperative code in imperative languages, but I can also see how it puts people off.
I think syntax, tools and such are "lesser" obstacles to overcome in the grand scheme of things.
and when I said "this page", I meant
ReplyDeletehttp://eddology.com/post/14592579289/busy-persons-clojure
I think you are right regarding Python versus Clojure. Still, many people will find Clojure better suited to their needs. I think keeping talking about it is important. As is working towards making the pain points less painful.
ReplyDelete@Nick Thanks for the link, I'll check it out when I get some free time.
ReplyDelete@Simon Definitely, we need to keep talking about Clojure. Look at the popularity of Haskell today. Their small community has pushed the message hard and they're no longer such a small community.
I think that new implementations (in Python as well as others) will eliminate most of the pain points. Clojure's pain points are mostly Java pain points.
On prefix notation:
ReplyDeleteIts only the most common convention that the common arithmetic operators are infix, true its what people are used to but it doesn't take long to get used to other forms (I also use reverse polish occasionally).
The biggest advantage though is there is no ambiguity, you don't have to remember order of precedence, there is no possibility of ambiguity.
I'm not sure where you get the idea that indentation is syntax.
The importance comes to the human not the computer, its to help people parse the language and the conventions developed by Lisp programmers over the years really do help that.
Its the same in any other language though, poor formatting hinders your understanding.
Hello there! I could have sworn I've been to this blog before but after browsing through many of the posts I realized it's new to me.
ReplyDeleteAnyways, I'm certainly happy I discovered it and I'll be book-marking it
and checking back regularly!
my blog :: vigrx enhancer