The nice effect of this site is that it takes you away from the grand scheme and makes you think about the icky details.
The first puzzle gets you to note that true is a valid Clojure word that evaluates to boolean true.
Next we have a simple piece of arithmetic illustrating the operator-first lisp type notation.
Next we have an example of a method call. In the expression
(.toUpperCase "hello world")
the first argument .toUpperCase must of course evaluate to a function - but the dot at the beginning indicates that this is a call to a method on a Java class - but which class? Clojure works this out from the type of the
next argument, the string "hello world".
The next tests introduce lists and vectors.
Lists you can create with a literal or a function call, as '(:a :b :c) or (list :a :b :c).
For vectors there is the literal form and two functions, so you can say [:a :b :c] or (vector :a :b :c) or (vec '(:a :b :c)).
What surprised me at this point is that the vector and the list are equal, that is:-
(= (list :a :b :c) (vector :a :b :c)) --> true
The function conj adds one or more new elements to a collection and returns a new collection. However, conj adds the elements "at an efficient insertion spot for the underlying data structure" (Halloway p.95)
This means that when you conj into a list the added elements go in at the beginning:-
(conj '(3 4) 2 1) => (1 2 3 4)
But for a vector the new elements go in at the end:-
(conj [1 2] 3 4) => [1 2 3 4]
When you conj an element into a set then the set decides whether to accept the new element and where to put it.
Clojure uses functions first, second and rest where in trad Lisp you would have car, cadr and cdr.
Anyway, a very nice site and it runs very smoothly and gives you the appropriate exception report when you do something invalid.