Monday, April 30, 2012

Why is Clojure hard to learn?

I've spent a good deal of time in the last few months using Clojure, and my experiences have been pleasant. As a Lisp dialect, it's automically a very interesting programming language. But even better, it's also a JVM language, and benefits from very tight integration with the JVM and with Java code itself.

However, all is not perfect in the Cloverse. Clojure has a very steep learning curve. While for the masters, it can be a powerful, supple, flexible tool, for the rest of us, it's esoteric, foreign, and opaque.

Why is this?

My belief is that this difficulty is, to a large degree, caused by the natural structure and organization of Clojure code, which is very different from the natural structure and organization of projects in mainstream programming languages. I will differentiate between four models of code organization, and show how Clojure's is hardest for the novice (but not for the master).

language type system paradigm list of methods/functions object supports methods/functions are typed interactive access to docs easy to use REPL
Java static object-oriented yes: compile-time (IDE autocompletion) yes yes: IDE feature no
Python dynamic object-oriented yes: run-time (limited IDE support possible) no yes: interactive `help` function yes
Haskell static functional no yes yes (limited) yes
Clojure dynamic function no no yes yes

Analysis/interpretation

What's missing? Note that with both Haskell and Clojure, since they're not object-oriented, it's not possible to easily find all of the functions that can be invoked on an object. Why? In object-oriented languages, the most useful methods are members of a class or object, and can be found "through" the object; whereas functions are not organized as "belonging" to an object; a function accepting an X could appear in any module or file (and indeed, it may make sense to do so). Although note that methods can be part of other classes (think 'util' or 'helper' classes), and indeed, such an organization can be difficult to grok.

This problem is mitigated to a certain extent in Haskell because functions are statically typed, thus, given the type of an object, all relevant functions can be looked up (check out Hoogle for an example).

There's no common REPL for Java (that I know of); I count this as a major negative for Java, because it makes it much harder to interact with code. However, this is more than offset by the fantastic IDEs, such as Eclipse and NetBeans, that have been created to help manage Java code bases. The key features of these programs are interactive access to lists of applicable methods, documentation, imports, automatic refactoring ...

Clojure enjoys neither Haskell's typing, which provides an important modicum of documentation, nor the luxury of specialized IDEs. Thus it's very difficult to find all the functions that an object supports.

How can this be fixed? I don't know, but I think the key lack is that of access to relevant information from within the programming environment, whether it applicable functions of docs. When someone figures out an effective way to implement this, expect Clojure to become very popular.

Summary

The problem that I believe Clojure is facing, and that likely all languages face in their infancy, is how to lower the barrier to entry, and make it easy for newcomers to effectively learn to use the language. An important aspect of this is how the information contained in function, object, and module documentation is accessed, indexed, and searched by the programmer. Clojure is lacking in this area, and therefore presents difficulties to newcomers.

7 comments:

  1. Okay... so this is definetly true if you want to write code the way you do in other languages.

    But clojure encourages you to define solutions to a problem w/o adding too much boilerplate, i.e. without creating a data structure for every nook-and-cranny of a domain.

    I think that IDEs encourage the opposite approach.

    ReplyDelete
    Replies
    1. That's not my point -- I'm not saying how Clojure should be done.

      I'm saying that I think learning Clojure is hard for novices because the information that is needed is hard to access.

      Delete
  2. okay - here goes take 2 :

    The reason this is hard for begginiers, is because begginers learned to think in objects, and they tend to overmodel their data (because we all learn not to use primitives for everything at an early stage).


    Map reduce is similar - its hard to learn because you have to unlearn some of the higher level object oriented approaches to development that we grow comfortable with very early on...

    ReplyDelete
    Replies
    1. I see what you're saying, but I don't want to harp on the OOP vs. FP issue (that's why I included Haskell). What I'm really trying to point out is that I believe that for every language you learn, and every library you use, you need a good grasp of the basics in order to work effectively. I think the beginner stage is about building up that understanding and reservoir of knowledge and examples between the ears. And I think Clojure is not (yet) as good at that as other languages. And so that's where I expect a lot of progress to be made in the near future!

      Delete
  3. Nice post, thank you.

    Personally I think that Light Table from Chris and people involved in the creation will make a revolution in this field. Conventional and mainstream tools will try to Copy the ideas from this tool.

    I am 100% sure that barrier to entry will get lowered, and that it will help other main stream programmers to begin to think about the problem they are solving.

    Clojure from my point of view is computational mathematics at its finest on Java Platform these days.

    I thank Rich Hickey that he risked so much in the early stages of Clojure Platform in 2008.

    ReplyDelete
    Replies
    1. Thanks for the comment. Looking forward to more Clojure in the near future!

      Delete
  4. It's not just finding information, it's the subtleties in using the information. For example, namespaces, use, 'use, require, import, load etc. can get confusing, but are required to achieve basic tasks like loading files and functions into the REPL. Hopefully, over time, there will be a "beginner way" to do things and this problem will fade. Also, Clojure is very flexible, another problem for beginners.

    ReplyDelete