Skip to content

Cheat Sheet: Clojure

gilch edited this page Nov 23, 2024 · 18 revisions

This is a cheat sheet, not a tutorial. It's meant to refresh your memory or help you find search terms for the docs, for those familiar with Clojure. Not all alternatives are macros. Not all macros are listed, only those that correspond to Clojure features.

For a more Clojure-like experience, also check out toolz (core functions), pyrsistent (persistent data structures), and Garden of EDN.

Clojure Special Forms Alternatives
def define
if if-else/when
do progn
let* let*from (does simple destructuring and self-shadowing),
letfn my#. Maybe type.
quote quote
var proxy#. See also: defvar, contextvars.
fn lambda, fun
loop/recur loop-from/recur-from
set! set! (items), set@ (attributes)
throw throw. See also: throw-from.
try engarde (prelude)
monitor‑enter / monitor‑exit Maybe enter (prelude) combined with the threading module and locks. Not really used in "user"-level Clojure.
Clojure Macros Alternatives
->/->> ->/-<>>
. (.bar self ...) (methods), foo.bar (attribute from identifier), @##' (attribute lookup tag), getattr (builtin function)
.. foo.bar.baz (from identifier) or -> with @#', like (-> foo @#'bar.baz)
alias alias
amap map and array.
and ands. Python's truthiness is different from Clojure's.
areduce /#, /XY#, functools..reduce
as-> -<>> with :<>. Maybe combined with my# or X# for repeats.
assert assure. See also: avow.
binding binding (see defvar, contextvars). Maybe unittest.mock.patch (like with-redefs).
bound-fn/bound-fn* Probably (.run (cxv#copy_context)-.
case case
comment Useless. Try ()_#(-) or similar. Trivial to implement yourself.
cond cond
cond->/cond->> Maybe my#(progn- with whens (imperative style).
condp my# on a cond
declare (define foo None), probably. Python mostly doesn't need it, but it affects template quotes, which mostly work anyway.
definline "Experimental" in Clojure. Define a macro (defmacro) and a function (defun) in terms of the macro, with the same name.
definterface abc., probably. Python is not Java.
defmacro defmacro
defmethod/defmulti deftypeonce/defun, probably. Maybe :@##functools..singledispatch, which is not properly reloadable (but neither are Clojure multimethods).
defn defun
defn- defun and prepend an underscore to the name. Python mostly doesn't enforce privacy, but this is the convention.
defonce defonce
defprotocol abc., probably. Python's not Java.
defrecord deftupleonce
deftype deftypeonce
delay (ft#cache O#-). (Call it to force/deref/@.)
deref (.get *foo*), if *foo* is a context variable.
doseq any-map
dosync No STM in Python (ClojureScript either, really). Maybe in-memory sqlite3.
dotimes any-map on a range
doto doto
extend-protocol Not applicable, duck typing.
extend-type Maybe register (if using @singledispatch). Python classes are mutable.
for Ensue, probably. Also the iterator builtins and itertools (and chain#). Maybe with my#. Maybe mix on a Python comprehension.
future concurrent.futures.
gen-class types..new_class. (See also: exec, type, deftypeonce, @dataclass.)
gen-interface abc., probably. Python's not Java.
if-let my# on if-else or when
if-not unless
if-some my# on if-else or when, with an is not None check or something.
import define on a fully qualified name. Prefer aliases.
io! Not applicable. No STM, but see sqlite3.
lazy-cat chain, chain#.
lazy-seq Ensue (prelude). See also: tee.
let destruct->. See also: let. (Yes, let is a macro in Clojure. It macroexpands in terms of let*.)
locking enter (prelude) with threading. locks.
memfn No need. Python's not Java.
ns prelude, alias. Need something to set _macro_, rather than *ns*.
or ors. Python's truthiness is different from Clojure's.
proxy, proxy-super type, probably. Usually not required due to duck typing (ClojureScript either).
pvalues concurrent.futures..map
refer define on a fully qualified name. E.g., (define _macro_.foo bar.._macro_.foo)
refer-clojure prelude, or custom variants.
reify type, probably. Usually not required due to duck typing.
require importlib., module handles, define, alias.
some->/some->> my# on ands
sync No STM, but see sqlite3.
time time#, timeit..timeit
vswap! Not applicable. (Everything's on the heap in Python.)
when when
when-first Wouldn't work in Python. Iterators are mutable. Empty collections are already falsey.
when-let my# on when
when-not unless
when-some my# on when, with an is not None check or something.
while takewhile, dropwhile, loop-from, Ensue (prelude).
Clojure with- Macros Alternatives (See enter from prelude)
with-bindings contextvars..copy_context.run
with-in-str with mk#patch on sys.stdin, replaced with an io..StringIO.
with-local-vars my#
with-open with contextlib..closing
with-out-str with contextlib..redirect_stdout
with-precision with decimal..localcontext
with-redefs with mk#patch
Clojure Special Reader Syntax Alternatives
#inst inst#
#uuid uuid#
*data-readers* _macro_
*default-data-reader-fn* __getattr__ (In _macro_'s class.)
#? Not applicable, but .#(cond- could be similar.
#?@ Not applicable, but .#` and ,@(cond- could be similar.
' '
\x "x". Use a length-1 string instead (also works in ClojureScript).
\space "\N{space}" (Any Unicode name, not case sensitive.)
; ; Beware these can be arguments for tags.
@ (.get-) for context vars. No STM types.
^ __annotations__ (for classes and functions, maybe with typing..Annotated). attach (only namespace types). weakref..WeakKeyDictionary (Only weakref hashable types. Try Pyrsistent for more hashable collections.)
#{-} (#-)
#"regex" re..compile#|regex|. Compiles as a pickle, so no better than run time, but re. allows string arguments and caches their patterns automatically.
#' proxy#. See also: defvar, contextvars.
#(-) %# or Xᵢ# from the macro tutorial. See also, O#, X#, XY#, XYZ#, XYZW#, en#X#/!##.
#_ _#
` `
~ , (Use an extra space or comment for grouping instead.)
~@ ,@
foo# (auto gensym) $#foo. Unlike Clojure, these also work in an unquote context.
Clone this wiki locally