2017-02
This article is about the Clojure programming language. It’s a jumble of:
The central place to look for Clojure-related links is the clojure.org community resources page. If my links below look sparse, it’s because I’m trying not to duplicate.
More Docs:
More Discussion:
More Leiningen:
More Web dev:
More ClojureScript:
More Emacs:
Clojars:
Finding Other Clojure Libraries:
lein new foo
.Moar!
See also:
Oh my goodness apropos
is useful. Pass it a regex or a string:
user=> (apropos #"-with$")
(split-with merge-with)
user=> (apropos "merge")
(merge-with merge merge-profiles unmerge-profiles)
Also do make use of doc
and source
.
Example of my-project/src/my_project/core.clj ns
macro:
(ns my-project.core
(:require [foo.bar :as fb]
[baz.qux :as bq])
(:import java.text.SimpleDateFormat
some.other.Class))
Remember:
When Clojure sees the unqualified foo
, it looks for foo’s var, then derefs that to get a value. If you just want the var itself, do #'foo
.
When Clojure sees the unqualified :bar
, it doesn’t go looking for anything – keywords just evaluate to themselves.
Clojure looks for foo
in the current namespace. If you’ve qualified the name, like my-stuff/foo
, it looks in the my-stuff
namespace, and my-stuff
may be an alias for some longer namespace name, ex., frobnicators.hydraulic.my-awesome-stuff
.
Keywords can be namespace-qualified, just like symbols, for example: :bar/foo
. Here, Clojure won’t care to go looking for the bar namespace, since keywords (including namespaced ones) just evaluate to themselves anyway.
Incidentally, a shortcut for making namespaced keywords: ::foo
–> :curr-namespace/foo
.
But here’s the tricky part: If you write ::bar/foo
(two colons), Clojure will try to resolve the namespace (thank you, Daniel!):
user=> ::foo
:user/foo
;; Double-colon'd namespaced keywords cause Clojure
;; to do namespace lookup:
user=> ::bar/foo
RuntimeException Invalid token: ::bar/foo
clojure.lang.Util.runtimeException (Util.java:221)
user=> ::str/foo
RuntimeException Invalid token: ::str/foo
clojure.lang.Util.runtimeException (Util.java:221)
user=> (require '[clojure.string :as str])
nil
user=> ::str/foo
:clojure.string/foo
user=> ::clojure.string/bar
:clojure.string/bar
;; And this works, since we're already here:
user=> ::user/foo
:user/foo
BTW, note:
user=> #'foo
CompilerException java.lang.RuntimeException: Unable to resolve
var: foo in this context, compiling:
(/tmp/form-init7070004536327442760.clj:1:1010)
user=> (def foo 42)
#'user/foo
user=> #'foo
#'user/foo
user=> (require '[clojure.string :as str])
nil
user=> #'str/join
#'clojure.string/join
Example val | Java class | Cast function |
---|---|---|
true |
java.lang.Boolean | boolean |
1 |
java.lang.Long | long |
1.2 |
java.lang.Double | double |
1N |
clojure.lang.BigInt | bigint |
1.2M |
java.math.BigDecimal | bigdec |
22/7 |
clojure.lang.Ratio | rationalize |
(If you need them, there’s also a handful more of specialized cast functions — byte
, char
, short
, int
, and float
— which get you instances of java.lang.Those.)
Numbers don’t auto-promote. Use the N
& M
numeric suffixes and the primed (arbitrary-precision) operators, such as +'
and *'
to get bigints and bigdecs.
Note that there’s also a
biginteger
function that gets you a java.math.BigInteger, but that’s not often needed, since Clojure comes with its own clojure.lang.BigInt.
0xab
, 017
, and 2r1111
all get you Longs. You can put a negative sign in front of any of those. Note that the “0x” and “0” prefixins are shorthand for the more general radix notation:
16rab = 0xab
8rab = 017
2e3
results in a double with the value 2 × 103.
not=
works like =
. There is no “not==”.
compare
is like Perl’s <=>
/cmp
.
comparator
will create a comparator from a predicate (though is rarely used, since Clojure does this implicitly for you).
(rand) ; decimal from 0 to under 1.0
(rand 5) ; decimal from 0 to under 5.0
(rand-int 5) ; int from 0 to 4
(rand-nth coll)
contains?
checks for the presence of a key, and when called on a vector, interprets indices as keys. To check for the presence of some item in a vector, use some
.
this | is shorthand for |
---|---|
#'x |
(var x) |
@x |
(deref x) |
^SomeType |
^{:tag SomeType} |
^:some-key |
^{:some-key true} |
All the Clojure collections are “seq-able”.
Note that, even though #{:a :b :c}
is seq-able, it’s not sequential (nor is it a seq, of course):
(sequential? #{:a :b :c})
;=> false
(seq? #{:a :b :c})
;=> false
(seq #{:a :b :c}) ; but it's seqable
;=> (:a :c :b)
Lists and vectors (and map entries, for that matter) are sequential.
Lists are seqs though:
map
, filter
, remove
, sort
, sort-by
reduce
for
(can take :when
and :while
options, can also take more than one pair in its binding vector)loop
& recur
If you can’t do it with map
/filter
/remove
/sort
, try reduce
.
If you can’t do it with reduce
, try for
.
If you can’t do it with for
, try loop
and recur
.
Note that many (most?) seq-producing functions are lazy. However, this may not always be obvious to you when working from the repl, since the repl eagerly evaluates everything to display it for you.
Put values into a map:
(def m {:a 1 :b 2})
(assoc m :c 3) ;=> {:a 1 :b 2 :c 3}
(conj m [:c 3]) ;=> same
(into m {:c 3}) ;=> same
;; `find` finds you a map entry given a key:
(find m :a) ;=> [:a 1]
(class (find m :a)) ;=> clojure.lang.MapEntry
contains?
tells you if a particular key is present in the given collection (works on vectors and sets too).
To get a value from a map:
To get a new map containing only the entries corresponding with the keys you specify:
You can use select-keys
on vectors too, which provides a way to grab just the elements you want, but you’ll get them unordered:
(select-keys [:a :b :c :d :e] [1 3 4]
;=> {4 :e, 3 :d, 1 :b}
(vals (select-keys [:a :b :c :d :e] [1 3 4]))
;=> (:e :d :b) ; out of order though
If you want them in order, maybe try:
To merge hashes, you can use merge
and can also into
, but note that into
only takes two args.
merge-with
merges maps but also allows you to merge or otherwise deal with keys that show up in more than one of the maps:
So, for example, if you want to merge a bunch of maps, and have each value of the resulting map be a vector of any vals present in any of the maps:
(defn collect-em-all
[accum x]
(cond (sequential? accum) (conj accum x)
:else (list accum x)))
(let [result (merge-with collect-em-all m1 m2 ...)]
...)
There’s a convenience reduce function just for associative colls: reduce-kv
.
select
is like filter
for sets.
Don’t really know what set/rename
does. What is “rel”, “xrel”, and “kmap”? Are sets called “relations”? XXX
project
as in “projection”; not as in “my project”. XXX
join
… XXX
To check if at least one element in a collection satisfies a given predicate, use some
.
To check if a collection contains a given item, also use some
(could maybe think of it as “at-least-one?”, except that it’s not a predicate):
(def xs [:a :b :c])
(some #{:a} xs) ;=> :a (which is true)
;; Rather than:
(some (fn [x] (= x :a)) ; Just returns a boolean.
xs) ;=> true
(def m {:a 1 :b 2})
;; See if any value of m is 2:
(filter (fn [[_ v]]
(= v 2))
m)
;;=> ([:b 2])
I read a call to
(some a-set coll)
as “Are any of the items incoll
ina-set
?”, which is the same as, “Are any of the items ina-set
incoll
?”If
a-set
contains only one item, it’s, “are any of the items ina-coll
the item ina-set
?”, which is the same as, “is the item ina-set
incoll
?”.
.indexOf
works on both strings and sequential collections:
(.indexOf "hello" "lo") ;=> 3
(.indexOf [:a :b :c :d] :c) ;=> 2
;; As of v1.8:
(str/index-of "hello" "lo") ;=> 3
get
is intended for maps, but will work on vectors too (since they are indeed associative). get
of course won’t work on lists, which are not associative (use nth
on those).
Not only can you choose what you want sorted (the items of the coll or some func of them), but you can choose the comparator to use (or create your own):
Example:
;; Specifying only the comparator:
(sort #(> (second %1) (second %2)) [[:a 5] [:b 2] [:c 7]])
;;=> ([:c 7] [:a 5] [:b 2])
;; Specifying only the keyfn:
(sort-by second [[:a 5] [:b 2] [:c 7]])
;;=> ([:b 2] [:a 5] [:c 7])
;; Specifying both keyfn and comparator:
(sort-by second > [[:a 5] [:b 2] [:c 7]])
;;=> ([:c 7] [:a 5] [:b 2])
cons
, next
, rest
, map
, for
, take
, drop
, interleave
, interpose
, sort
, … all give you back a seq.
conj
and into
give you back the data type you start with.
split-at
and split-with
return a 2-element vector (where each element is a seq).
For creating nested data structures, note the following:
user=> (for [row [:a :b :c]]
(for [col [1 2 3]]
[row col]))
(([:a 1] [:a 2] [:a 3])
([:b 1] [:b 2] [:b 3])
([:c 1] [:c 2] [:c 3]))
user=> (for [row [:a :b :c]
col [1 2 3]]
[row col])
([:a 1] [:a 2] [:a 3] [:b 1] [:b 2] [:b 3] [:c 1] [:c 2] [:c 3])
filter
☯ remove
drop-last
↔ butlast
(though, you can pass n to drop-last)take-last
↔ drop
drop-while
↔ take-while
take-nth
gets every nth element. Note there’s no “drop-nth”.
keep
is like map
, but keeps only the non-nil results. Likewise for keep-indexed
and map-indexed
.
rest
vs. next
:
(seq [:a]) ;=> (:a)
(seq []) ;=> nil
;; The "*rest* of them" implies a list:
(rest [:a]) ;=> ()
(rest []) ;=> ()
;; (`rest` never returns nil.)
;; though, "what's *next*" could mean nil:
(next [:a]) ;=> nil
(next []) ;=> nil
;; Regardless, if they have something to return,
;; it will be a seq.
(rest [:a :b]) ;=> (:b)
(next [:a :b]) ;=> (:b)
Different behaviour depending upon what’s natural for the particular type of arg:
(conj [1 2 3] 4)
;=> [1 2 3 4]
(conj '(1 2 3) 4)
;=> (4 1 2 3)
(peek [1 2 3])
;=> 3
(peek '(1 2 3))
;=> 1
(pop [1 2 3])
;=> [1 2]
(pop '(1 2 3))
;=> (2 3)
Note the symmetry of functions for creating data structures:
literal syntax | takes coll arg(s) | takes indiv args |
---|---|---|
'() |
seq |
list |
[] |
vec |
vector |
{} |
zipmap |
hash-map |
#{} |
set |
hash-set |
That is: the shorter names take collections as args, and the longer-named functions take individual args.
Implicit do
: fn
, defn
, let
, when
, when-let
, when-not
.
letfn
can be convenient, since all functions can see the other functions (regardless of the order in which you define them).
Note the convenience macros if-let
and when-let
.
for
for
makes sequences, and can optionally take :when
and :while
in its binding vector:
:when
is like a built-in “next” or “continue”::while
is like a built-in “last” or “break”:for
also can take more than one pair in its binding vector, to give you nested lists (but note that if you use :while
within one of these, it will only terminate the inner loop (thanks, amalloy!)).
(def a (repeat 3)) ;=> a is (3 3 3 ...)
(def b (repeatedly f) ;=> b is ((f) (f) (f) ...)
(def c (iterate f 1)) ;=> c is (1,
;; (f 1),
;; (f (f 1)),
;; (f (f (f 1))) ...)
(def c (constantly 3)) ;=> (c) => 3
;; (c 1) => 3
;; (c "hi" 7 :yo) => 3
repeat
repeatedly
constantly
identity
complement
iterate
returns a lazy seq of x, (f x), (f (f x)), … For example,
fnil
See also comp
and partial
.
There’s defn
and defn-
(for non-public functions), otherwise, not much use of that trailing dash.
A leading dash signifies gen-class methods. As an example, for apps, your main is named “-main
”.
A trailing single-quote is sometimes used on names to mean “prime”. You see it on, for example, *
vs *'
where it indicates arbitrary precision.
A trailing star * means either “primitive, part of the bootstrap, implementation detail”, or “somewhat like its namesake, but couldn’t think of a better name for it” (thanks, technomancy). :)
The only place you see a leading star (aside from *'
) is with *1
, *2
, *3
, & *e
, which are used in the repl.
Leading and trailing stars are for dynamic vars, and are sometimes referred to as “earmuffs” (*hi*
).
Underscores are generally not used.
Embedded ->
is used in function names denoting that they turn something into something else (this->that
).
Trailing ?
is for predicates.
->
and ->>
are also used for the threading macros, and new (as of v1.5) threading macros as->
, cond->
, cond->>
, some->
, and some->>
.
Leading ->
is for creating records.
#foo/bar [1 2 3]
. After Clojure has read the regular literal at the end, it then invokes some function referred to by foo/bar on that regular literal, returning the result. Tagged literals which aren’t namespace-qualified are reserved for Clojure (for example, #uuid and #inst).
Functions that return a lazy sequence: map
, filter
, for
, take
, drop
(and their kin). Note that loop
/recur
is not lazy.
doall
and dorun
force realization. They are eager.
cons
and list*
won’t force evaluation of a potentially lazy seq passed as their last arg.
In the book Clojure Programming, the author points out, “In Clojure, laziness is restricted to sequences”. That is, everything else being eagerly evaluated.
See also:
lazy-seq
next
and rest
… “head retention”. XXXno newline | gives you a newline | |
---|---|---|
human-readable | print |
println |
eval-able | pr |
prn (autoflushes) |
print
and println
are for human readers.
pr
and prn
are for getting output that looks like Clojure code.
prn
is hot (flushed after each call); pr
, print
, and println
are not. Of course, you can always call (flush)
yourself.
Note: you can pass slurp
a url.
Symmetry: pr-str
↔ read-string
In Java-land, non-sourcecode data files that you want to provide with your app are called “resources”.
When you create an app with lein
, it starts you off by default with an empty my-proj/resources
directory into which these resource files may go.
The clojure.java.io/resource
function returns a URL to the given resource, which you can then use to read it in and make use of it:
;; assuming clojure.java.io :as io
(let [stuff (io/reader (io/resource "stuff.whatever"))
other (io/file (io/resource "other.whatever"))]
...)
And remember too that slurp
can slurp in a URL (what io/resource returns).
You can make use of Java source code from your Clojure code if necessary. Put your Java source code into my-proj/src/java/ and then set :java-source-paths in your project.clj accordingly.
Summary of Java interop:
Description | Java | Clojure |
---|---|---|
create an instance | foo = new Foo(a, b) |
(Foo. a b) |
call instance method | foo.bar(a, b) |
(.bar foo a b) |
access instance field | foo.x |
(.x foo) |
set instance field | foo.x = 7 |
(set! (.x foo) 7) |
call static method | Foo.baz(a, b) |
(Foo/baz a b) |
access static field | Foo.moo |
Foo/moo |
More interop notes:
doto
to call numerous methods on a given object. Works similar to thread-first.Creating a local repository: XXX
Find the full list of available Leiningen plug-ins at https://github.com/technomancy/leiningen/wiki/Plugins.
Into the :plugins vector of your :user profile, add:
To start serving files from the current working directory, on, say, port 5002:
lein simpleton 5002 >> server.log 2>&1 &
To stop the server, find it with ps
and then kill $PID
. (Actually, you’ll find two java processes there which you’ll need to shut down — one for lein and one for java.)