views:

1028

answers:

4

Which lesser-known but useful features of Clojure do you find yourselves using? Feel free to share little tricks and idioms, but try to restrict yourselves to Core and Contrib.

I found some really interesting information in answers to these similar questions:

There are many more "Hidden feature" questions for other languages, so I thought it would be nice to have one for Clojure, too.

+9  A: 

The read-eval reader macro: #=

(read-string "#=(println \"hello\")")

This macro can present a security risk if read is used on user input (which is perhaps a bad idea on its own). You can turn this macro off by setting *read-eval* to false.

Arthur Ulfeldt
+12  A: 

Clojure has an immutable, persistent queue datatype, PersistentQueue, but it doesn't (yet?) have literal reader syntax or Clojure wrapper functions, so you have to create one via a Java call. Queues conj (push) onto the rear and pop from the front with good performance.

user> (-> (clojure.lang.PersistentQueue/EMPTY)
          (conj 1 2 3)
          pop)
(2 3)

Lists conj onto the front and pop from the front. Vectors conj onto the rear and pop from the rear. So queues are sometimes exactly what you need.

user> (-> ()
          (conj 1 2 3)
          pop)
(2 1)
user> (-> []
          (conj 1 2 3)
          pop)
[1 2]
Brian Carper
+9  A: 
(defn foo [a & [b c]] ...)

You can destructure the rest argument.

Update:

The latest commit to the git repo (29389970bcd41998359681d9a4a20ee391a1e07c) has made it possible to perform associative destructuring like so:

(defn foo [a & {b :b c :c}] ...)

The obvious use of this is for keyword arguments. Note that this approach prevents mixing keyword arguments with rest arguments (not that that's something one's likely to need very often).

(defn foo [a & {:keys [b c] :or {b "val1" c "val2"}] ...)

If you want default values for keyword arguments.

dnolen
Hm, I didn't realise that editing in the hot news would give me majority share in this answer... I think I've only now got the idea behind this community wiki thing. @dnolen: Please don't hesitate to "retake" this if it matters somehow.
Michał Marczyk
+4  A: 

You can apply functions to infinite argument sequences. For example

(apply concat (repeat '(1 2 3)))

produces a lazy sequence of 1,2,3,1,2,3... Of course for this to work the function also has to be lazy with respect to its argument list.

Rafał Dowgird
There is a better way of doing this (cycle '(1 2 3))
nickik
@nickik: Of course - `(repeat '(1 2 3))` was just meant as an example infinite sequence of sequences to show how `(apply concat ...)` works.
Rafał Dowgird