General documentation / cheat sheets for various languages and services

clojure

References:

basic types

:id :first-name keywords evaluate to themselves. I.e., they're just keyword literals. They're not pointers or references to something else. To convert a string to a keyword: (keyword "name").
:js/alert ::port namespaced keywords are basically keywords, but it's more than just a convention faciliated by the double-colon syntax. A :: prefix, as with ::port, produces a keyword with the current namespace prepended to the given name. So after calling (ns server.core), ::port would evaluate to :server.core/port.

Keywords can only have one slash, but you can declare a keyword with a different namespace than the current one.

There's also an interesting effect that arises in destructuring. If you destructure a map with namespaced keys, the variable name you put into the scope is just the local (post-/) part of the keyword. E.g., (defn print-server-port [{:keys [server.core/port]}] (println port)).

split find-first zero? symbols represent other things, like functions or values. They can contain alphanumeric characters, *, +, !, -, _, ', and ?, but cannot start with a numeral.
"The end" "span { }" strings can contain literal newlines
\K \newline characters are unquoted escape sequences.
42 +42 -42 0.001 1e100 2e-16 numbers use decimal syntax.

collections

Commas are optional; they are treated as whitespace.

'(user :name "Lester") '(1 8 19 47) '(a, alt, end) lists are usually immediately evaluated (i.e., (verb noun) would try to call verb with noun as the argument), but ' "quotes" the list, producing a list literal. (list x y) does the same thing as '(x y). Lists have singly-linked performance characteristics.
[user1, user2, admin1] [0 1 1 2 3 5] vectors are like lists, but don't invoke function application. Like list, you can use (vector 1 10) to create a vector like [1 10]. Vectors have random-access performance characteristics.
{:first "Chris" :last "Brown"} {:k "abbr", :v "cb"} maps are key-value pairs.
{"Chris" "Brown" "H"} #{101, 103, 107} sets are unordered collections of unique elements. Set literals cannot contain duplicates. Use set to create a set from other collections (and handle duplicates): (set [101 103 107 101]).

collection operations

(cons x seq) Returns a new seq that prepends x to seq.
(map f coll) (map f & colls) Call f for each item in coll, and returns a new (lazy) sequence with each return value of calling f.

To evaluate strictly (non-lazily), use (mapv ...) (which has exactly the same signatures, but no transducer option) or wrap your in a (doall (map ...)).


The second form is rare, and is like zipping first and then running the resulting tuples through f. E.g.:

(map + [1 2 3] [10 20 30]) (11 22 33)

Using the multi-collection form, the zipper stops zipping at the end of the shortest coll in colls.

Omitting the collection(s) returns a transducer.

(conj coll x) (conj coll x & xs) Returns a new collection with the x (or x and xs) added.

The specific operation — prepend vs. append (or perhaps even insertion) — and thus the resulting order — depends on the type of collection (the "concrete type").

(conj [1 2] 3) [1 2 3] (conj '(1 2) 3) (3 1 2)

If coll is nil, it's treated as if it were () (the empty list).

(list* xs) (list* x & xs) Returns a new seq prepending all items but the last to the last item. Basically it's the same as (list ...), but the last argument gets splatted in at the end.
(into to from) conj's each of from onto to.

There is also a transducer form.

(concat) (concat x) (concat x y) (concat x y & zs) Returns a lazy seq combining x, y, and each item in zs, in order from left to right. x, y, and each item in zs must be "ISeqable".
(flatten xs) Recursively flattens xs into a single sequence. Returns the empty list if xs is not a sequence.

To non-recursively flatten a list: (apply concat xs)

Or, without even using concat: (mapcat identity xs)

(mapcat f & xs) Flat-maps f across xs. f should take a single argument x (from xs) and return a collection.

It's effectively the same (equivalent?) as (apply concat (map f xs)).

(filter f xs) Return a lazy sequence of each x from xs where (f x) returns true.

Omitting the collection ((filter f)) returns a transducer.

(remove f xs) remove is the opposite of filter. (remove f xs) is equivalent to (filter (complement f) xs).
(filterv f xs) Strict version of filter; returns a vector.

(Unlike filter, does not have a transducer overload.)

(Also, there is no removev.)

(keep f xs) Returns a lazy sequence of the results of calling (f x) on each x in xs, dropping nil values. (keep f xs) is equivalent to (remove nil? (map f xs)).
(doall coll) Forces a lazy sequence to evaluate, and returns the sequence.
(dorun coll) Forces a lazy sequence to evaluate, and returns nil.
(doseq seq-bindings & body) Like (for seq-bindings & body) but non-lazy and returns nil.

basic syntax

(def name "Chris") variables are set at the top level in the current namespace.
(def ^{:private true} conn-string "pg:db:root:5ecr3t") Variables can be made private to the module in which they are defined.
(def ^{:constant true} rand-seed 2016) Variables can be declared constant, though I'm not sure what the point is, what with Clojure being immutable and all. Maybe for JVM-compliance?
(fn [x] (* x x)) functions are anonymous, but can be set to a variable with def.
(defn square "Multiply the argument by itself" [x] (* x x)) (defn name args body) is sugar for (def name (fn args body)), but also facilitates supplying a string commenting on the function's purpose.
(defn- connect [conf] (...)) Functions declared with defn- are private to the module in which they are defined.
(defn range-size ([from to] (- to from)) ([to] (range-size 0 from))) function overloading (a.k.a., "multiple arities") allows differentiating function behavior based on the number of arguments it's called with.
(defn join-name [first last & middles] (str first " " (join " " middles) " " last)) A function's variadic argument is signaled by & and comes last in the argument vector.
(map #(str "(" % ")") ["c" "h" "b"]) ("(c)" "(h)" "(b)") The reader macro makes anonymous function syntax more concise. #(body) is kind of like shorthand for (fn [%1] (body)), but adapts the argument vector based on the number of %-prefixed names supplied in body.
% is short for %1, but the latter is preferred if your #(...) function takes more than one argument.
%& captures the variadic remainder, i.e., all the arguments beyond the highest %N present.
(let [x 100 y (* x 2)] (println (str "Starting at (" x ", " y ")")) [x, y]) Starting at (100, 200) [100 200] let takes a vector of symbol-expression pairs to declare immutable variables in local scope, then evaluates all the following expressions, returning the final expression.
(do (println (str "Starting at (0, 0)")) [0, 0]) Starting at (0, 0) [0 0] do is like let, but without the local variables.
(loop [x 0] ... (recur (inc x))) loop is a lot like let, but allows jumping back to just after binding the variables with recur. Otherwise, it will return the value of the last expression of whatever dead end it hits.
(for [x (range 4) y (range 2)] [x y]) ([0 0] [0 1] [1 0] [1 1] [2 0] [2 1] [3 0] [3 1]) for is like let, but each variable's expression must be a sequence, and it iterates through the cross product of all sequences.
The bindings vector supports three modifiers:
  • :let for nested bindings
  • :while for specifying an exit condition, which is like take-while (evaluated before each loop)
  • :when for skipping certain conditions, which is like filter

namespaces and imports

As far as I can tell, dots in a namespace/package/module name are equivalent to alphanumerics except that they specify directory descent rather than file name, when mapping module names to filesystem location.

(ns io.github.chbrown.docs) Sets the current namespace to io.github.chbrown.docs, which should usually be in the file PROJECT_ROOT/src/io/github/chbrown/docs.clj.
(ns ... (:require org.anist.render)) Can now call (org.anist.render/text "Hello")
(ns ... (:require [org.anist.render :as render])) Can now call (render/text "Hello")
(ns ... (:require [org.anist.render :refer [html pdf text]])) Can now call (text "Hello")
(ns ... (:require [org.anist.render :refer :all])) Wildcard import.
(ns ... (:import java.time.ZonedDateTime)) Import class from the new Java 8 time implementation. Can call it like (ZonedDateTime/now).
(ns ... (:import [java.time Duration Instant ZonedDateTime])) Import multiple classes from the java.time namespace.
(ns ... (:use ...)) :use is deprecated as of Clojure 1.4; there's nothing :use can do that :require + :refer (:refer was added in Clojure 1.4) can't do better.
(require 'org.anist.render) (import 'java.time.ZonedDateTime) In the REPL, you may want to require or import another module on the fly; this form takes a quoted "libspec" (see the full (ns ...) examples above).

Java interop

java.text.Normalizer$Form/NFKC Java allows declaring classes inside other classes, which are accessed statically, and slightly differently than classes nested in another layer of namespace. Instead of using . to access the inner class, use $.

java.text.Normalizer.normalize("Å", java.text.Normalizer.Form.NFC) in Scala/Java is equivalent to (java.text.Normalizer/normalize "Å" java.text.Normalizer$Form/NFC) in Clojure.

functional building blocks

(apply f xs) (apply f x & xs) (apply f x y & xs) Call f with each x in xs as its arguments.

If multiple arguments are given, everything after f are combined as if with (list* ...), i.e., everything up until the last argument are prepended to the last argument.

Useful for splatting a list into multiple function arguments, since there is no function invokation syntax sugar like Python's stringify(' ', *separators).

Suppose you have a list of strings, (def my-strings '("Chris" "Brown")), that you want to join into a single string, with no separators. But (str x & ys) joins each of its arguments, not a list. (str my-strings) would simply return a string representation of the list.

(str my-strings) "(\"Chris\" \"Brown\")"

Instead, you'd want to use apply:

(apply str my-strings) "ChrisBrown"

(partial f & args) Curries f and returns a new function that will use each arg in args as an argument when eventually calling that new function.

Clojure is not generally lazy, so otherwise calling a function with an insufficient number of arguments will raise an arity error.

(comp) (comp f) (comp f g) (comp f g & fs) Compose multiple functions into a single function; the right-most function will be called first, then the next right-most, etc.

(apply (comp a b c) x) is equivalent to (a (b (c x)))

(complement f) Return a new function that takes the same arguments as f, does the same thing as f, but returns the boolean opposite of what f returns. I.e., true if f returns false or nil, false otherwise.

(complement f) is equivalent to (comp not f).

(cond & clauses) Each clause is a pair of two functions; if the first returns true, the second gets called. The clauses are tested in order, and the (cond ...) itself returns the result of the second function in the first clause whose first function returns true. The last clause's test function can be :else, which always evaluates as if true (so it operates as an "otherwise" or default: in a switch construct.)

threading operators

(-> x & forms) The thread-first operator.

Call each form in forms with x (or the value returned by the previous form) inserted as the second item in the form (the first argument to the function).

If a form takes only one argument, you may omit the surrounding parentheses.

(doto x & forms) Just like ->, except that all of the forms are just side-effects; the flow behaves as if each form in forms returned x.
(->> x & forms) The thread-last operator. (Also called the "thrush" operator?)

Call each form in forms with x (or the value returned by the previous form) appended as the last argument.

If a form takes only one argument, you may omit the surrounding parentheses.

References:

atoms

(atom value) Creates a new Atom with the value value, and returns the atom.
(deref atom) @atom Returns the value of atom (as opposed to the Atom itself). Also known as "dereferencing", I'm guessing because (deref ...) was the original syntax, and the @ sugar came later.
(reset! atom value) Sets atom to value (discarding atom's current value), and returns value.
(swap! atom fn & args) Calls fn with the current value of atom (and args, if any) and sets the atom's value to the result (also, returns the new value of atom).

(def counter (atom 0)) @counter 0 (swap! counter inc) 1 (swap! counter inc) 2 @counter 2

Often you'll see an atom that's a map, where most changes to it consist of setting a single key to a new value.

(def person (atom {:first-name "Chris"})) (swap! person assoc :last-name "Brown") @person {:first-name "Chris", :last-name "Brown"}

(compare-and-set! atom oldval newval) Calls (reset! atom newval) iff (= @atom oldval). Returns the boolean value of (= @atom oldval).

destructuring

Work in progress

References:

Recipes

Utility functions that seem like they ought to be in the standard library.

map-values

(defn map-values “contruct a new map with all the values of the given map passed through f” f kvs)

Alternatively, this can be written a bit more verbosely but perhaps more properly/Clojurely with reduce like so:

(defn map-values “contruct a new map with all the values of the given map passed through f” f kvs)

update-when

The standard (update m k f) adds an entry to m with the key k and the value (f (get m k)), even if (get m k) is nil and even if f returns nil.

It's perhaps more Clojureish to imagine that all maps contain every key with the value of nil, but sometimes it's more practically useful to distinguish between key-value pairs with nil values and keys that are not contains?-ed by the map m.

(defn update-when “Like update but only calls f if m contains k” m k f & args)

Development

These packages are very useful development / testing helpers:

Their use is described below.

Testing

Test your entire project:

lein test

For nicer test failure explanations, add the dependency [pjstadig/humane-test-output "0.8.1"] and the following :injections to your ~/.lein/profiles.clj:

(require 'pjstadig.humane-test-output)
(pjstadig.humane-test-output/activate!)

Then use the ordering (clojure.test/is (= expected actual)) for proper error messages.

To calculate test coverage; add [lein-cloverage "1.0.9"] to your list of plugins, then run:

lein cloverage

Code style

To list suggested changes in git diff format, add [lein-cljfmt "0.5.6"] to your plugins, and run:

lein cljfmt check

To make the changes in place, run:

lein cljfmt fix

To ‘lint’ your Clojure code, add the plugin, [jonase/eastwood "0.2.3"], and run:

lein eastwood

To optimize/modernize your imports, add the dependency [slamhound "1.5.5"] and the alias {"slamhound" ["run" "-m" "slam.hound"]}, and then run:

lein slamhound src/

Dependencies

To list your project’s dependencies are not the latest available version, add [lein-ancient "0.6.10"] to your plugins, and run:

lein ancient

To check the dependencies in ~/.lein/profiles.clj, too, run (from anywhere):

lein ancient check-profiles