# Clojure
^539406
## Reference
- [home page](https://clojure.org)
- [clojure-toolbox.com](https://www.clojure-toolbox.com) - A categorized directory of libraries and tools for Clojure
- [clojuredocs.org](https://clojuredocs.org) - community-powered documentation and examples
- [seqfind.com](https://seqfind.com/) - Clojure(script) code explorer designed to help the community learn by example. The aim is to highlight popular libraries along with their most used functions and namespaces.
- minutia
- [On why symbols and vars are separated in Clojure](https://news.ycombinator.com/item?id=2467809) and why Clojure's compilation unit is top-level forms and its implications.
### Libraries
- https://github.com/cgrand/xforms
- [nubank/matcher-combinators](https://github.com/nubank/matcher-combinators) - Library for creating matcher combinator to compare nested data structures
## Extensible Data Notation (edn)
[source](https://github.com/edn-format/edn)
- **edn** is an **E**xtensible **D**ata **N**otation. A superset of **edn** is used by Clojure to represent programs, and it is used by Datomic and other applications as a data transfer format.
- **edn** supports a rich set of built-in elements, and the definition of extension elements in terms of the others.
- **edn** is a system for the conveyance of _values_. It is not a type system, and has no schemas. Nor is it a system for representing objects - there are no reference types
- There is no enclosing element at the top level. Thus **edn** is suitable for streaming and interactive applications.
### Built-in elements
[source](https://github.com/edn-format/edn#built-in-elements)
- `nil`
- booleans - `true` and `false`
- strings - enclosed in `"double quotes"`, multi-line, C escape characters `\t, \r, \n, \\, and \"` are supported
- characters - `\<c>`, `\newline`, `\return`, `\space`, `\tab`
- symbols - begin with a non-numeric character and can contain alphanumeric characters and `. * + ! - _ ? $ % & = < >`.
- If `-`, `+` or `.` are the first character, the second character (if any) must be non-numeric.
- `: #` are allowed as constituent characters in symbols other than as the first character.
- `/` has special meaning in symbols. It can be used once only in the middle of a symbol to separate the _prefix_ (often a namespace) from the _name_, e.g. `my-namespace/foo`. `/` by itself is a legal symbol, but otherwise neither the _prefix_nor the _name_ part can be empty when the symbol contains `/`.
- If a symbol has a _prefix_ and `/`, the following _name_ component should follow the first-character restrictions for symbols as a whole.
- keywords - Keywords are identifiers that typically designate themselves. They are semantically akin to enumeration values. Keywords follow the rules of symbols, except they can (and must) begin with `:`, e.g. `:fred` or `:my/fred`.
- integers
- floating point numbers
- lists - sequence of values, e.g. `(a b 42)`
- vectors - sequence of values, random access, e.g. `[a b 42]`
- maps - associative unordered collection, e.g. `{:a 1, "foo" :bar, [1 2 3] four}`
- sets - collection of unique values, e.g. `#{}`, `#{:a b [1 2 3]}`
### tagged elements
[see source](https://github.com/edn-format/edn#tagged-elements)
### built-in tagged elements
- instance - [[time#^141c48|RFC-3339]] formatted tagged string, e.g. `#inst "2022-04-19T14:50:56.381-04:00"`
- [UUID](http://en.wikipedia.org/wiki/Universally_unique_identifier) - e.g. `#uuid "e70d408a-6bac-21c0-b899-16eac0246bff"`
## Built-in Tooling `tools.deps`, `tools.build` and [[cli|CLI]]
[As of version 1.9](https://clojure.org/news/2017/12/08/clojure19), Clojure ships with [spec](https://github.com/clojure/spec.alpha) and a [[cli]] interface, including a dependency management library (`tools.deps`) and build tools (`tools.build`). These are Cognitect's take on contracts and build tooling, holes previously filled by community libraries like [Schema](https://github.com/plumatic/schema) and [leiningen](https://leiningen.org).
### Resources
- official
- guides
- [getting started](https://clojure.org/guides/getting_started)
- [deps and cli](https://clojure.org/guides/deps_and_cli)
- [tools.build](https://clojure.org/guides/tools_build)
- reference
- [deps and cli](https://clojure.org/reference/deps_and_cli)
- [tools.build tasks](https://clojure.github.io/tools.build/)
- [clojure-doc.org cookbook on cli builds](https://clojure-doc.org/articles/cookbooks/cli_build_projects/)
- [tomekw guide](https://tomekw.com/clojure-deps-edn-a-basic-guide/)
- [kozieiev guide](https://kozieiev.com/blog/clojure-cli-tools-deps-deps-edn-guide/)
- [Clojure CLI flags](https://practical.li/blog/posts/clojure-which-execution-option-to-use/)
- useful libraries
- [seancorfield/build-clj](https://github.com/seancorfield/build-clj)
- [cognitect-labs/test-runner](https://github.com/cognitect-labs/test-runner)
- [practicalli/clojure-deps-edn](https://github.com/practicalli/clojure-deps-edn) - not endorsing the idea behind
the project its [deps.edn has many example aliases worth copy-pasting as a starting point](https://github.com/practicalli/clojure-deps-edn/blob/live/deps.edn).
### `clj` and `clojure`
`clj` is just an [[cli#^c02b97|rlwrap]] wrapper for `clojure` and provides a much better `stdin` editing experience
- emacs keybinding navigation, word edits
- history
```bash
rlwrap -r -q '\"' -b "(){}[],^%#@\";:'" "$bin_dir/clojure" "$@"
```
- Use `clojure` for scripting and [[CICD]]
- use `clj` for interactive shell sessions.
```
Start a REPL clj [clj-opt*] [-Aaliases] [init-opt*]
Exec fn(s) clojure [clj-opt*] -X[aliases] a/fn? [kpath v]* kv-map?
Run tool clojure [clj-opt*] -T[name|aliases] a/fn [kpath v] kv-map?
Run main clojure [clj-opt*] -M[aliases] [init-opt*] [main-opt] [arg*]
Prepare clojure [clj-opt*] -P [other exec opts]
```
#### Help Functions
[source](https://clojure.org/reference/deps_and_cli#_help_functions)
> The `help/doc` and `help/dir` functions introspect how a tool can be used. Because the `:deps` alias does not include the project classpath, these are not currently useful when executing functions in your own project.
> - `-X:deps help/doc` - show the doc strings and parameter lists of the functions given with key `:ns` or function specified by an additional key `:fn`; if neither given then `:ns-default` is used
> - `-X:deps help/dir` - prints the public functions in namespace provided with key `:ns` or `:ns-default` if not given
For usages, see [[#Built-in deps Alias]]
#### Options
- [[#clj-opt s]]
- [[#-M exec-opt]] - run `-main` or a script
- [[#-X exec-opt]] - run a function
- [[#-T exec-opt]] - run a tool
- [[#-P exec-opt]] - prepare
- [[#-A aliases]] - run a REPL
##### `clj-opt`s
```
-Jopt Pass opt through in java_opts, ex: -J-Xmx512m
-Sdeps EDN Deps data to use as the last deps file to be merged
-Spath Compute classpath and echo to stdout only
-Spom Generate (or update) pom.xml with deps and paths
-Stree Print dependency tree
-Scp CP Do NOT compute or cache classpath, use this one instead
-Srepro Ignore the ~/.clojure/deps.edn config file
-Sforce Force recomputation of the classpath (don't use the cache)
-Sverbose Print important path info to console
-Sdescribe Print environment and command parsing info as data
-Sthreads Set specific number of download threads
-Strace Write a trace.edn file that traces deps expansion
-- Stop parsing dep options and pass remaining arguments to clojure.main
--version Print the version to stdout and exit
-version Print the version to stderr and exit
```
##### `-M` exec-opt
Invokes `clojure.main`, to execute the `-main` function in a namespace or execute a Clojure script.
```bash
# show docs on main-opts
clj -M --help
# invoke -main in core namespace
clj -M --main core
clj -M -m core
# execute script.clj
clj -M script.clj 1 2 3
# == script.clj ==
# (println "Script invoked with args: " *command-line-args*)
```
Given this alias in [[#deps edn]]:
```clojure
{
:aliases {
:project/run {:main-opts ["-m" "project.core"]}
}
}
```
Can invoke with `-M`
```bash
clojure -M:project/run
```
Aliases chain
```bash
# call with :project/run and :profile aliases
clojure -M:project/run:profile
```
##### `-X` exec-opt
Invoke a function that takes a map:
```
clojure [clj-opt*] -X[aliases] [namespace/fn] [kpath v]* kv-map?
```
Given this function
```clojure
(ns core)
(defn echo-args [argm] (println argm))
```
```bash
clojure -X core/echo-args :key1 :val1 '{:foo :bar}'
# {:key1 :val1, :foo :bar}
```
`-X` is the preferred invocation style over `-M` [in some cases](https://github.com/cognitect-labs/test-runner#invoke-with-clojure--m-clojuremain).
##### `-T` exec-opt
[official docs](https://clojure.org/reference/deps_and_cli#_using_named_tools)
Invoke a tool by name.
To manage tools, use the built-in `tool` tool.
> Yo dawg, I heard you like tools. So I put a `tools` tool in your Clojure tool.
List functions for tool management
```bash
clojure -A:deps -Ttools help/dir
```
Note activating a tool with `-T` activates a default namespace. In the example above, `clojure.tools.tools.api` is active instead of the `:deps` alias default `clojure.tools.cli.api`. To find a tools default namespace:
```bash
clojure -A:deps -Ttools show :tool tools
# {:lib io.github.clojure/tools.tools,
# :coord
# {:git/tag "v0.2.5",
# :git/sha "76f728dce63f7b881f4e5705ba0d59d795d56f11"}}
# Default namespace: clojure.tools.tools.api
```
All you need to be a tool is include this key tree in project's `deps.edn`
```clojure
{;;...
:tools/usage
{:ns-default the.tool.namespace
:ns-aliases {} #_"map of aliases to lib symbols"}
;;...
}
```
###### Some Useful Tools
- [antq](https://github.com/liquidz/antq#clojure-cli-tools-1103933-or-later) - manage outdated dependencies
##### `-P` exec-opt
[source](https://clojure.org/reference/deps_and_cli#_prepare_for_execution)
> The -P flag can be used with any other execution mode to "prepare" but not execute.
Useful for forcing environment side-effects like downloading maven dependencies, e.g. inside a [[Docker]] image build.
##### `-A` aliases
Run a REPL in context of aliases. It's also used to add alias context to other switches like `-S`.
```bash
clojure -Atest -Spath
```
### `deps.edn`
Config file, analogous to [leiningen](https://leiningen.org) `project.clj`, with the distinction that the latter is executable and the former is [[#Extensible Data Notation edn|just data]].
#### Precedence
[source](https://clojure.org/reference/deps_and_cli#_merging_deps_edn)
> The `deps.edn` files found from the source locations (with Clojure tool modifications by any options) are merged to form one master deps map. [...]
> The operation is essentially `merge-with merge`, ==except for the `:paths` key, where only the last one found is used (they are not combined)==.
In ascending precedence order
- Root - `$(dirname $(readlink -f $(which clj)))/../deps.edn` ^223ebd
- User
- If `$CLJ_CONFIG` is set, then use `$CLJ_CONFIG` (explicit override)
- If `$XDG_CONFIG_HOME` is set, then use `$XDG_CONFIG_HOME/clojure` (Freedesktop conventions)
- Else use `$HOME/.clojure` (most common)
- Project - the `deps.edn` in the current directory
- External - a `deps.edn` map passed on the command line
The sources can be modified or inspected by the following options:
- `-Sverbose` - print all source locations
- `-Sdeps` - pass the config data on the command line
- `-Srepro` - omit the user deps source (other sources will be used if found)
#### Caching
See [classpath caching](https://clojure.org/reference/deps_and_cli#_classpath_caching)
#### Built-in :deps Alias
The [[#^223ebd|Root]] `deps.edn` file has a built-in `:deps` alias.
```
-X:deps mvn-install Install a maven jar to the local repository cache
-X:deps git-resolve-tags Resolve git coord tags to shas and update deps.edn
-X:deps find-versions Find available versions of a library
-X:deps prep Prepare all unprepped libs in the dep tree
```
```bash
# list functions in the namespace: clojure.tools.cli.api
clojure -X:deps help/dir
# show docstrings for functions in the namespace: clojure.tools.cli.api
clojure -X:deps help/doc
# show docstrings for functions in the help ns-alias (part of :deps alias)
clojure -X:deps help/doc :ns help
```
## 3rd Party Build Tools
### leiningen
before there was [[#deps.edn]] there was [leiningen](https://leiningen.org)
- https://leiningen.org/
- [how clojure babies are made](https://www.flyingmachinestudios.com/programming/how-clojure-babies-are-made-lein-run/) - fundamentals of launching and building clojure programs by hand
## Static Checks
### clj-kondo
Setup on [[MacOS]]
```bash
brew install borkdude/brew/clj-kondo
# in project, initialize caches
clj-kondo --lint "$(clojure -Spath)" --dependencies --parallel --copy-configs
# practicalli/clojure-deps-edn alias
clojure -M:lint/clj-kondo
# if clj-kondo is on the path, doom emacs ':checkers syntax' integration will "just work"
```
- [clj-kondo/clj-kondo](https://github.com/clj-kondo/clj-kondo#installation)
- [borkdude/flycheck-clj-kondo](https://github.com/borkdude/flycheck-clj-kondo) for [[emacs]] integration
Doom emacs cheatsheet for fly-check linting
```
<Space> c x - bring up lint list window
C-c ! n - next lint error from cursor
C-c ! p - previous lint error from cursor
```
### cljfmt
[idiomatic](https://github.com/bbatsov/clojure-style-guide) Clojure code formatting
- [cljfmt](https://github.com/weavejester/cljfmt) is a library and [[#leiningen]] plugin for formatting Clojure code.
- [cljfmt-graalvm](https://github.com/pmbauer/cljfmt-graalvm) is a native, CLI packaging of cljfmt
- provides same stdio interface as used by other language formatting tools, e.g. `gofmt` for [[golang]]
- compatible with [format-all](https://github.com/lassik/emacs-format-all-the-code) [[emacs]] module
- in addition, exposes same interface as cljfmt lein plugin
- `diff`
- `fix`