How practical is Clojure?
johnfn.github.com
johnfn.github.com
Error messages can definitely be tricky to figure out. A stacktrace, however, will often give enough information. Simply start looking down the stack for the first function that is part of your code base. The function may or may not have a line number. This depends on if you've loaded the source as a file, or sent an individual function to the repl on its own. In the latter case the line number information is simply not available to the language.
Using the stack traces solves 90% of issues I encounter. If I need line numbers, I restart the REPL and make sure that information is present. It's rare indeed that a stacktrace doesn't help at all, although it happens. I also use print debugging frequently. The REPL makes this technique a lot more reasonable than it is in say, C.
What would you suggest to improve the debugging/error situation?
--
If I had to choose a single biggest weakness for clojure adoption, I would say the lack of good documentation and also standardized process that is often so important when working in larger teams. The core documentation is good for experience developers, but lacks examples that many others find useful. The books clojure books are good, and clojuredocs.org is a great idea that has yet to get enough traction to become the standard go to place for documentation.
That said, it is still a young language and the community is working hard at addressing these issues.
For example, is www.webnoir.org filling this need in the web space? Would a better clojure.org with Noir like examples fill the gap?
And then there are simple questions like how to make a concurrent application. The docs go on at length about how Clojure helps concurrent applications, but not a whole lot about what is a reasonable way to make one in Clojure. You're just told how great it is for the task and then kind of thrown in with a list of functions and told to get to it.
I agree though, lots more examples would be nice!
However, these are issues that rarely come up in idiomatic Clojure. Most of the time you don't need your own collection classes, or new types that work like functions. It is possible, but since it's a rare need, I'm not surprised the documentation on how to do it is indirect at best... deftype is probably the best tool if you need something low-level like that, or defrecord if you just want something that works like a map.
Your 'simple' question isn't exactly simple either. The famous ants simulation is a fair example of a concurrent application, but often the design depends on the sort of concurrency you need, and the simple question suddenly becomes much more difficult. More examples wouldn't hurt, of course.
Anyway, my point is, this is pretty much the state of the Clojure documentation right now:
On Clojure.org:
- List of features
- Alphabetical list of functions stretching as far as the eye can see
On ClojureDocs.org:
- List of functions by namespace
- Long list of functions by "category"
- A cheatsheet consisting of the long list of functions by category with descriptions removed
ClojureDocs is much better, but it still isn't enough to even implement a simple facsimile of hash-set or figure out how to start multiple threads in order to take advantage of all those swanky concurrency features. (The concurrency example is actually something practical I wanted to do. I have a slightly quirky bin-packing algorithm that I wanted to parallelize and I felt stumped staring at the list of functions. Finally I found a Stack Overflow post that said to just use Java's Thread.run with a Clojure function.)
The documentation is mostly terse, but there is http://java.ociweb.com/mark/clojure/article.html which is more tutorial-like; though it's probably getting a bit old by now.
1) Most of the time I resort to reading the actual source.
2) There are many libraries which have native clojure documentation on each function, but lack a website summarizing it.
3) Trying to figure out how all the various web components fit together is very time consuming.
3.1) How do ring sessions handle security? (they default to a memory store, but you need to dig to find this, I don't know if the cookie store uses encyrption)
3.2) ClojureQL is still in heavy development, but the documentation is lacking answers to many frequently asked questions. EG:
3.3) How does one execute a series of statements in a transaction?
3.4) How does one retrieve the id of the record just inserted?
There are answers. For the first, you can use clojure.java.jdbc, or clojure.contrib.sql, given some constraints. For the second, you can't, but the latest dev snapshot can.
3.5) How do you execute arbitrary SQL? (you can in batch with jdbc, but not all statements work in batch)
3.6) session expiry, a critical feature. But you need to dig to find hozumi/session-expiry. Also, it doesn't work with sandbar's stateful sessions in my experience. All not documented.
3.7) security restrictions are another huge problem for clojure web frameworks. Sandbar's are ok, but still limited and not particularly performant. I'll try to get some code released soon on this front.
3.8) Understanding how ring and it's requests work is a challenge. There should probably be a small book chapter explaining the architecture of this. I understand it, but it took a lot of reading on mailing lists and ultimately the source code to figure it out.
4) Beyond documentation. Clojure web frameworks are based on composing many small components. This is great and has many strengths beyond those of other frameworks. However, a lot of users are looking for a turnkey "do this, do that" solution. They want to know the best standard practice. This is process, something that gives strengths to frameworks like Ruby on Rails.
While I would not suggest abandoning the composability of clojure web frameworks, having a standardized large scale framework with standardized process would go a long way to getting more widespread adoption.
For example, a framework with recommendations for large scale code organisation like model view controller, or similar functional equivalents, along with recommendations for standardized modules and coding practices.
Webnoir is still too much of a micro framework to handle these needs. We don't need to abandon flexibility and composability. However, there needs to be a manual of best practices along with code that makes it easy to use for common web app development, all details included.
Above all, a central resource tying all these points together is what is needed. I too want to help with this.
> What would you suggest to improve the debugging/error situation?
The easiest possible improvement, and something I might write soon, is a simple stack trace parser that would extract only the relevant information. If Clojure errors said "Probable error at this line" first, and then gave me the stack trace after, that would be a lot more user friendly, especially for beginners. And it seems pretty straightforward to parse out lines that have the current file name in them, etc.
http://clojure.github.com/clojure/branch-master/clojure.repl...
The lein help command does more than simply print a string, it searches for plugins available on your system. To measure the startup time of lein perhaps you should do:
% time lein version ~
Leiningen 1.6.1 on Java 1.6.0_26 Java HotSpot(TM) 64-Bit Server VM
lein version 0.75s user 0.05s system 130% cpu 0.612 total
Less than a second, not bad.> time lein shows about 10 seconds to display all the output, and then it hangs for about a minute more before the process completes.
So there's a problem on your system. Most people don't have that problem. Check your plugins.
Saying "oh fix your whatever" is just passing the buck. This is a frequent enough problem to be a major issue. If there are more than a few of these issues people will simply move elsewhere. Rightfully so too.