I don't know if this is just their test runner or whether it is a problem in Clojure proper, but it's really frustrating to see "Assertion failed" with zero description of the runtime error. I have to fire up a REPL and reverse engineer the expected value, instead of just observing what the expression evaluates to as in the ruby koans.
As an example:
"But watch out if you try to pop nothing"
(= __ (try
(catch IllegalStateException e "No dice!")))
That code causes an error that looks like this:
Problem in /home/clueless/clojure-koans/src/koans/02_lists.clj
But watch out if you try to pop nothing
(= __ (try (pop (quote ())) (catch IllegalStateException e "No dice!")))
That's just a transliteration of the Clojure expression from my source code. It's not even as good as a line number, because it's not greppable. If I were actually to encounter this in a failing test, you had better believe I would want to know what the right-hand-side actually evaluated to in context, not just what the compiled expression looks like.
Yeah, I hear you. There's definitely room for improvement here. I'm not sure what you mean by not greppable - the file is listed, as is the name of the particular koan. If there's a way to get line numbers displayed here that would be great.
I agree it does make it easier to solve when you can see what you're trying to evaluate to. It was actually a conscious decision to make that not be the case, because it seemed too easy to just fill in the blanks without thinking about what should go there.
In this case it's a Java wart, yes, but the same thing happens with other parts of the language. Another example:
"Conjoining an element to a list can be done in the reverse order"
(= __ (conj '(:a :b :c :d :e) 0))
Well OK, so is `conj` just `cons` with reversed argument order, or does it append to the other end of the list? My Lisp intuition tells me that the first is more likely, but the test failure doesn't show you anything, you have to use trial and error or fire up a REPL.
Not really either. Conj acts on collections (which can be lists, vectors, sets or hash maps), and adds the second and subsequent arguments to the collection in a type-dependent way. For a list, your hunch is correct, in that it's a bit like a reversed-argument 'cons', except that you can have add more than one item to the list;
Exercises on http://www.4clojure.com seem like a much easier way to get your feet wet with Clojure. It's good when new users can try a language out right in their browsers, without having to install any additional software.
I agree that 4clojure.com seems an easier way to get started. However, if you're already setup with Clojure on your machine, using clojurekoans.com has the advantage of allowing you to work in your editor of choice.
Since this is for new Clojure users I think the install instructions should include how to install the koans with Leiningen. The instructions say to install Leiningen but once you've got that working you won't know how to use it to install the koans.
I agree, it's a bit confusing how it's written, and I'm not even really sure what using lein would buy you when doing the koans. If anyone is interested in using lein, here's what you need to look at: https://github.com/functional-koans/lein-koan
git clone firstname.lastname@example.org:functional-koans/clojure-koans.git
lein koan run
I don't agree, I'd advise not to try Leiningen until you're comfortable enough with the parenthesis, the REPL and finish the koans themselves. This is 'getting your feet wet on Clojure', koans style. No need to introduce yet another tool when you're not dealing with the issues which Leinengen solves: managing library dependencies and configuration.
I remember I did: the koans first, then tried several exercises on the 4clojure website, then learned about Leinengen and only then I moved into 'projects'.
Learn Leiningen- not only because it makes Clojure simple and pleasurable to use, but because it'd be a fantastic tool no matter what language it was part of.
Project skeletons (new new), command line scripting (via lein exec), deployment, the wonderful 'lein ring server', custom plugins... and for those who just want to get their feet wet, 'lein repl' brings the ocean to you.
My initial reaction was to upvote @eccp, based on my experience with leiningen the first time round. Long story short: went around in circles following outdated (but seemingly comprehensive) guides that twisted my mind with hopeless combinations of Ant, Maven, Leiningen, emacs, slime and swank, among others. Basically gave up after a while, but was fortunate to get some encouragement here on HN, and went back in with just leiningen and emacs. I recall that was just the right mix, and as you say, lein repl pretty much brought the ocean to me.
Right, this needed to be cleaned up and clarified. The only thing you have to do is `lein koan run`, which was listed as an option but the ordering was confusing. I've reworked it a bit now, but feel free to open an issue/PR if things are still hazy: https://github.com/functional-koans/clojure-koans-web
Indeed, I'm trying to wrap my head around it now. It's a shame, this looked like a nice fun way to just drop in to playing around with Clojure, but it turns out that it's being bit of a hassle. Not that I don't think there should be a little effort involved! It's just that my expectations did not match up to reality.
This is the first time I've seen something like this, but it's greatly broadened my knowledge of Clojure over the past few hours. I've always had trouble trying to find out where to begin. Lisps are foreign to me, and functional programming was and is still a mostly foreign concept. However, things like this that are so simple and understandable make such great introductions.
Kudos to the authors, and you have a thumbs up from me.
As a somewhat recent practicer of tdd, I find that the koans + tdd approach is more rounded: I'm forced to learn/use a function/aspect that I might have glossed over. And occasionally a particularly nice usage of syntax jumps out and gets adopted.
I did a few Project Euler (http://projecteuler.net) problems in Clojure after doing the koans. I found it really helpful to implement solutions in some imperative or multi-paradigm language, and then go back and do the solutions again in Clojure. Each problem made me curious about the best way to solve it in Clojure, which led to lots of learning.