27

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.

Community
  • 1
  • 1
danlei
  • 14,121
  • 5
  • 58
  • 82

5 Answers5

23

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
  • 71,150
  • 28
  • 166
  • 168
  • WOW. popping 100000 items off a list my computer takes ~12ms. Converting the list to a queue AND popping everything off takes ~0.2. That's a huge help in the program I'm writing. – MBCook Nov 12 '11 at 03:38
13
(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
  • 18,496
  • 4
  • 62
  • 71
11

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.

Michał Marczyk
  • 83,634
  • 13
  • 201
  • 212
Arthur Ulfeldt
  • 90,827
  • 27
  • 201
  • 284
8

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
  • 43,216
  • 11
  • 77
  • 90
6

From the increasingly good ClojureDocs site an idiom using juxt http://clojuredocs.org/clojure_core/clojure.core/juxt

;juxt is useful for forking result data to multiple termination functions
(->> "some text to print and save to a file"
  ((juxt
     println
     (partial  spit "useful information.txt"))))

Alex Stoddard
  • 8,244
  • 4
  • 41
  • 61