Ideally, I was hoping to start a more in-depth discussion about the
pros and cons of "programming in the large" in Clojure than just
waxing poetic about Clojure/Lisp's capabilities in the abstract :)

Yes, much of the initial excitement around Clojure comes from the
feeling of "Wow, I can do so much with so little code".  But at some
point, all projects grow.  I'm thinking that by now, there may be
enough people using Clojure in large projects and on large teams to
offer some good feedback about how well that works.

My Clojure codebase is somewhere around 2-3kloc and I already feel
like I'm bumping up against some frustration when it comes time to
refactor, maintain, and extend the code, all while keeping up with
ongoing changes to libraries, contrib structures, and Clojure
versions.

I want to hear war stories from those with even larger code bases than
mine.  Has it proven to be a major hassle on large projects to avoid
circular dependencies in the modules?  Are the lack of debugging
tools, documentation tools, and refactoring tools holding you back?
Anyone miss static typing?

One of my main gripes is that some of Clojure's built-ins return
nonsensical results (or nil), rather than errors, for certain classes
of invalid inputs.  To me, one of the main benefits of functional
programming is that debugging is generally easier, in large part
because failures usually occur within close proximity of the flaw that
triggered the failure.  Erlang, in particular, has really promoted the
idea of "fail fast" as a way to build robust systems.  But Clojure's
lack of a "fail-fast" philosophy has burned me several times, with
hard-to-track-down bugs that were far-removed from the actual cause.
The larger my code grows, the more this annoys me, reminding me too
much of my days tracking down bugs in imperative programs.

One specific example of this is get, which returns nil whenever the
first input isn't something that supports get.  For example, (get 2 2)
 produces nil.  This becomes especially problematic when you pass
something to get that seems like it should support get, but doesn't.
For example, (get (transient #{1}) 1) produces nil, when there's
absolutely no reason to think that (get (transient #{1} 1) would
behave any differently from ((transient #{1}) 1).

-- 
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