Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Hicham Omari edited this page Nov 14, 2025 · 4 revisions

Basic Tips

  • N and M suffixes on numeric literals create BigInt and BigDecimal values, respectively. Clojure BigInt is distinct from Java BigInteger, but you can convert with the biginteger fn.

  • The return value of def can be derefed, e.g. @(def x 1).

  • recur also works in fns, including #( ).

  • Babashka provides these namespace aliases:

    • clojure.set as set
    • clojure.string as str
  • Many JDK classes and methods are available. See Babashka's classes.clj for an exact list.

I/O

  • Use prn instead of println for numbers and symbols.
  • doto can be useful for printing complicated intermediate expressions.
  • Often you can use a quoted symbol instead of a string, e.g. "Fizz" => 'Fizz.
  • A Lisp formatter implementation is available as clojure.pprint/cl-format. It can be useful in some situations, despite the long name.

Reference

Looping

There are many of ways to loop in Clojure. Here's some advice on when to use what:

  • To loop a fixed number of times for side effects, use dotimes.
    • If you're using a constant, a character literal can be used instead of an integer, which sometimes saves bytes and/or chars.
  • To loop over a sequence for side effects, use doseq.
    • Use a single doseq for nested loops over multiple sequences.
    • run! can be situationally occasionally useful too.
  • To produce a sequence, then use map/filter/keep/etc.
    • for can be situationally useful too.
  • To loop with one state variable, use nth and iterate.
  • To loop over a sequence with one state variable, use reduce.
    • Sometimes you can save by using the two-argument version.
  • Otherwise, use recursion
    • Ideally an anonymous short function with recur. This requires tail recursion and doesn't allow nesting with other short functions.
    • Even a non-short function is better than loop.

Ironically, the loop macro is never optimal.

Handling Arguments

(mapv #(println %)*command-line-args*)
(doseq[a *command-line-args*](println a))

Usually mapv is best, but doseq is better when you have other nested short fns.

Indexing

There're a few different ways to get a value from a sequence:

(ds idx)               ; Shortest, but only works for vectors, sets, and maps; no default and errors when out of range
(ds idx default?)      ; Has default, but only works for maps
(get ds idx default?)  ; Nil/default when out of range, but only for indexed sequences
(nth ds idx)           ; Works for all sequences, even lazy ones

Conditionals

(if cond x y)          ; Short circuits, you can leave the false section out to return nil, needs a truthy or (falsey/nil) condition
(and/or cond x)        ; Short circuits, multiple conditions
(case n v x default)   ; Short circuits, checks specific values, has default
({v x}n default)       ; Same as case, but no short circuit
([x y]n)               ; Needs a numeric 0/1 condition
(get[x y]n default)    ; 0/1 condition or non-short-circuiting default

Syntax-quoting

Syntax-quoting can be used instead of sequence fns in a variety of cases:

(concat a b)
; vs
`(~@a~@b)

(cons a b)
; vs
`(~a~@b)

All sequences can be spliced inside syntax-quoting, including strings, sets, maps, and nil.

Vector and set literals can also be used:

(conj s a)
; vs
`#{~@s~a}
; vs
`[~@s~a]

Map literals work too, but require an even number of forms inside.

Clone this wiki locally

Morty Proxy This is a proxified and sanitized view of the page, visit original site.