Clojure Hodgepodge

John Gabriele

2017-02

This article is about the Clojure programming language. It’s a jumble of:

Some Links

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:

Moar!

Talks

See also:

Articles

Docs in the REPL

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.

Namespaces, import, and require

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:

Name Resolution

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

Numeric Types

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.

Comparison and equality

(=  1 1.0) ;=> false
(== 1 1.0) ;=> true

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).

Random

(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)

Oddities

(conj)       ;=> []
(conj [])    ;=> []
(conj nil)   ;=> nil
(conj nil 5) ;=> (5)
* * *

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.

Misc Syntax

this is shorthand for
#'x (var x)
@x (deref x)
^SomeType ^{:tag SomeType}
^:some-key ^{:some-key true}

Sequences

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:

(seq? '(1 2 3))  ;=> true
(seq?  [1 2 3])  ;=> false

Transforming sequences

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.

Hashmaps

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:

(m :a)        ;=> 1
(:a m)        ;=> 1
(get m :a)    ;=> 1
(get m :a 3)  ;=> 1
(get m :x 3)  ;=> 3

To get a new map containing only the entries corresponding with the keys you specify:

(select-keys {:a 1 :b 2 :c 3 :d 4} [:b :d])
;=> {:d 4, :b 2}

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:

(defn get-these
  [v ks]
  (remove nil? (for [k ks]
                 (get v k))))

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:

(merge-with (fn [curr-val this-val]
              (str curr-val this-val))
            m1
            m2
            ...)

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.

Sets

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

Collections

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 in coll in a-set?”, which is the same as, “Are any of the items in a-set in coll?”

If a-set contains only one item, it’s, “are any of the items in a-coll the item in a-set?”, which is the same as, “is the item in a-set in coll?”.

.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).

Sorting

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):

(sort                      coll)
(sort            a-compar  coll)
(sort-by  keyfn            coll)
(sort-by  keyfn  a-compar  coll)

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])

Patterns, Symmetries, Misc

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])
* * *

filterremove

drop-lastbutlast (though, you can pass n to drop-last)
take-lastdrop
drop-whiletake-while

take-nth gets every nth element. Note there’s no “drop-nth”.

(drop-last 2 coll)
(take (- (count coll) 2) ;
      coll)              ; Same.

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.

Control Structures

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:

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!)).

Repetition and related functions

(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
returns a lazy, possibly-infinite seq of whatever value you passed to it.
repeatedly
takes a func of no args (presumably w/ side-effects), and returns a lazy, possibly-infinite seq of calls to it.
constantly
returns a function that always has the same return value, regardless of what you pass it.
identity
returns whatever you pass into it
complement
returns a function that returns the opp truth val of the one you passed it.
iterate

returns a lazy seq of x, (f x), (f (f x)), … For example,

fnil
takes a function, and returns a function which is the same, but which will replace a nil arg to it with a default value. Doesn’t change the arity of the function you give it — just lets you specify a default arg (or args) if nil is passed to it.

See also comp and partial.

Naming Conventions

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.

Terminology

Predicate
a function that returns true or false. One that takes 2 args might be referred to as a “binary predicate”, if you’re the sort who likes to name those kinds of things.
tagged literal
is a pound sign, followed by a namespace-qualified name, a space, and then some typical Clojure literal. For example: #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).
Reader Conditional
A new (as of v1.7.0) feature to support writing Clojure code once but have it usable across multiple Clojure implementations. Looks like it has replaced the earlier “Feature Expressions” proposal (as well as the briefly announced then unannounced “Feature Macros” proposal).

Laziness

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:

Reading and writing

  no 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-strread-string

Resources

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).

Using Java in your Clojure projects

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.

Java Interop

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:

Leiningen

Creating a local repository: XXX

Plug-ins

Find the full list of available Leiningen plug-ins at https://github.com/technomancy/leiningen/wiki/Plugins.

Simpleton

Into the :plugins vector of your :user profile, add:

[lein-simpleton "x.y.z"]

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.)