Merge branch 'main' of git.sr.ht:~marcuskammer/emacs.d

This commit is contained in:
Marcus Kammer 2022-08-25 08:32:38 +02:00
commit 39f9d6c993
586 changed files with 277787 additions and 88 deletions

View file

@ -1,66 +1,3 @@
;; (defun mk-show-modeline ()
;; (interactive)
;; (setq mode-line-format
;; '(("-" mode-line-mule-info
;; mode-line-modified
;; mode-line-frame-identification
;; mode-line-buffer-identification " "
;; mode-line-position
;; mode-line-modes
;; (which-func-mode
;; ("" which-func-format "--"))
;; (global-mode-string
;; ("--" global-mode-string)) "-%-")))
;; (defvar mode-line-format-current
;; (symbol-value 'mode-line-format)))
;; (defun mk-hide-modeline ()
;; (interactive)
;; (setq mode-line-format nil))
;; (defun mk-write-mode-enable ()
;; (setq olivetti-body-width 73)
;; (olivetti-mode)
;; (mk-hide-modeline))
;; (defun mk-write-mode-disable ()
;; (olivetti-mode)
;; (mk-show-modeline))
(defun me/split-windows-horizontal (count-windows)
"Split windows horizontal by equal width."
(interactive "nHow many splits? ")
(delete-other-windows)
(let ((width (/ (window-total-width) count-windows)))
(dotimes (i (1- count-windows))
(split-window-right (- width)))))
(defun me/split-windows-vertical (count-windows)
"Split windows vertical by equal width."
(interactive "nHow many splits? ")
(delete-other-windows)
(let ((height (/ (window-total-height) count-windows)))
(dotimes (i (1- count-windows))
(split-window-below (- height)))))
(defun me/split-h3 ()
(interactive)
(me/split-windows-horizontal 3))
(defun me/split-v3 ()
(interactive)
(me/split-windows-vertical 3))
;; Set transparency of emacs
(defun transparency (value)
"Sets the transparency of the frame window. 0=transparent/100=opaque"
(interactive "nTransparency Value 0 - 100 opaque: ")
(set-frame-parameter (selected-frame) 'alpha value))
;; (if (display-graphic-p)
;; (add-hook 'after-init-hook (lambda () (org-agenda-list) (me/split-h3)))
;; (org-agenda-list))
(defvar mk/useful-websites
'(("https://regexr.com/" regex debug)
("https://regex101.com/" regex debug)
@ -90,22 +27,86 @@
("<.+>" "matching html")
("<\/?(?:p|a|b|img)(?: \/)?>" "matchig specific tags")))
(defun me/list-files (folder suffix)
;; (defun mk-show-modeline ()
;; (interactive)
;; (setq mode-line-format
;; '(("-" mode-line-mule-info
;; mode-line-modified
;; mode-line-frame-identification
;; mode-line-buffer-identification " "
;; mode-line-position
;; mode-line-modes
;; (which-func-mode
;; ("" which-func-format "--"))
;; (global-mode-string
;; ("--" global-mode-string)) "-%-")))
;; (defvar mode-line-format-current
;; (symbol-value 'mode-line-format)))
;; (defun mk-hide-modeline ()
;; (interactive)
;; (setq mode-line-format nil))
;; (defun mk-write-mode-enable ()
;; (setq olivetti-body-width 73)
;; (olivetti-mode)
;; (mk-hide-modeline))
;; (defun mk-write-mode-disable ()
;; (olivetti-mode)
;; (mk-show-modeline))
(defun mk/split-windows-horizontal (count-windows)
"Split windows horizontal by equal width."
(interactive "nHow many splits? ")
(delete-other-windows)
(let ((width (/ (window-total-width) count-windows)))
(dotimes (i (1- count-windows))
(split-window-right (- width)))))
(defun mk/split-windows-vertical (count-windows)
"Split windows vertical by equal width."
(interactive "nHow many splits? ")
(delete-other-windows)
(let ((height (/ (window-total-height) count-windows)))
(dotimes (i (1- count-windows))
(split-window-below (- height)))))
(defun mk/split-h3 ()
(interactive)
(mk/split-windows-horizontal 3))
(defun mk/split-v3 ()
(interactive)
(mk/split-windows-vertical 3))
;; Set transparency of emacs
(defun transparency (value)
"Sets the transparency of the frame window. 0=transparent/100=opaque"
(interactive "nTransparency Value 0 - 100 opaque: ")
(set-frame-parameter (selected-frame) 'alpha value))
(defun mk/show-agenda-list ()
(if (display-graphic-p)
(add-hook 'after-init-hook (lambda () (org-agenda-list) (me/split-h3)))
(org-agenda-list)))
(defun mk/list-files (folder suffix)
(let ((regexp (concat "\\." suffix "$")))
(directory-files folder nil regexp)))
(defun me/build-file-suffix ())
(defun mk/build-file-suffix ())
(defun me/copy-files (src-dir dst-dir suffix)
(defun mk/copy-files (src-dir dst-dir suffix)
(let ((src-files '())
(src-dir (expand-file-name src-dir))
(dst-dir (expand-file-name dst-dir)))
(dolist (file (me/list-files src-dir suffix) src-files)
(dolist (file (mk/list-files src-dir suffix) src-files)
(let ((src-file (expand-file-name (concat src-dir "/" file)))
(dst-file (expand-file-name (concat dst-dir "/" file))))
(add-to-list 'src-files src-file)
(copy-file src-file dst-file t)))))
(defun me/delete-files (lst)
(defun mk/delete-files (lst)
(dolist (file lst)
(delete-file file t)))

View file

@ -81,6 +81,8 @@
("https://www.greenpeace.org/usa/rsslatest.xml" nature climate blog)
("https://blog.rust-lang.org/feed.xml" rust blog news)
("https://twobithistory.org/feed.xml" history blog coding)
("http://planet.clojure.in/atom.xml" clojure news hacking jvm java)
("https://taonaw.com/index.xml" emacs blog)
("https://www.phoronix.com/rss.php" linux news blog)
)
elfeed-search-filter "@4-day-ago +unread"))

View file

@ -32,9 +32,14 @@
(use-package nov
:hook (nov-mode . visual-line-mode)
:mode ("\\.epub\\'" . nov-mode)
:init
(add-hook 'nov-mode-hook #'shrface-mode)
:config
(setq nov-text-width 82
nov-variable-pitch t)
(require 'shrface)
(setq nov-shr-rendering-functions '((img . nov-render-img) (title . nov-render-title)))
(setq nov-shr-rendering-functions (append nov-shr-rendering-functions shr-external-rendering-functions))
(when (eq system-type 'windows-nt)
(when (directory-name-p "c:/msys64/")
(setq nov-unzip-program "c:/msys64/usr/bin/unzip.exe"))))
@ -87,20 +92,20 @@
(string-match "/usr/src/linux" (buffer-file-name)))
"linux"
"gnu")))
(add-hook 'c-mode-common-hook 'me/c-mode-style-hook)
(defun me/c-mode-compile-command-hook ()
;; if no makefile use gcc for compile command
(unless (or (file-exists-p "makefile")
(file-exists-p "Makefile"))
(set (make-local-variable 'compile-command)
(concat "gcc " "-Wall " "-g " buffer-file-name " -o "
(file-name-sans-extension buffer-file-name)))))
(add-hook 'c-mode-common-hook 'me/c-mode-compile-command-hook)
(defun me/c-mode-compile-on-save ()
;; compile on save hook
(make-local-variable 'after-save-hook)
(add-hook 'after-save-hook (lambda () (compile compile-command))))
(add-hook 'c-mode-common-hook 'me/c-mode-compile-on-save))
(add-hook 'c-mode-common-hook 'me/c-mode-style-hook))
;; (defun me/c-mode-compile-command-hook ()
;; ;; if no makefile use gcc for compile command
;; (unless (or (file-exists-p "makefile")
;; (file-exists-p "Makefile"))
;; (set (make-local-variable 'compile-command)
;; (concat "gcc " "-Wall " "-g " buffer-file-name " -o "
;; (file-name-sans-extension buffer-file-name)))))
;; (add-hook 'c-mode-common-hook 'me/c-mode-compile-command-hook)
;; (defun me/c-mode-compile-on-save ()
;; ;; compile on save hook
;; (make-local-variable 'after-save-hook)
;; (add-hook 'after-save-hook (lambda () (compile compile-command))))
;; (add-hook 'c-mode-common-hook 'me/c-mode-compile-on-save))
(use-package js-mode
:ensure nil

View file

@ -18,8 +18,7 @@
(width . 90)
(height . 64)
(alpha . 100)
(horizontal-scroll-bars)
(vertical-scroll-bars)))
(horizontal-scroll-bars)))
'(delete-by-moving-to-trash t)
'(diary-file
"d:/UserData/marcus.kammer/OneDrive - Siemens AG/documents/Diary/diary")
@ -66,7 +65,7 @@
'(org-roam-directory "d:/UserData/marcus.kammer/OneDrive - Siemens AG/org-roam/")
'(org-web-tools-pandoc-sleep-time 1.0)
'(package-selected-packages
'(mpv subed ob-http ob-go powershell ox-reveal org-web-tools org-tree-slide org-roam elfeed erc-image magit go-translate simple-httpd slime racket-mode web-mode go-mode geiser-guile geiser-racket geiser eglot nov shrface vertico smartparens emojify ace-window olivetti rainbow-delimiters helpful doom-modeline doom-themes all-the-icons-dired all-the-icons use-package))
'(cider mpv subed ob-http ob-go powershell ox-reveal org-web-tools org-tree-slide org-roam elfeed erc-image magit go-translate simple-httpd slime racket-mode web-mode go-mode geiser-guile geiser-racket geiser eglot nov shrface vertico smartparens emojify ace-window olivetti rainbow-delimiters helpful doom-modeline doom-themes all-the-icons-dired all-the-icons use-package))
'(plantuml-default-exec-mode 'jar)
'(plantuml-jar-path "~/AppData/Local/Programs/plantuml/plantuml.jar")
'(python-indent-guess-indent-offset nil)
@ -91,4 +90,4 @@
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(font-lock-keyword-face ((t (:foreground "#81A1C1" :slant italic))))
'(variable-pitch ((t (:height 1.3 :family "Roboto Condensed")))))
'(variable-pitch ((t (:height 1.3 :family "Ubuntu Condensed")))))

View file

@ -0,0 +1,216 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: About</title>
<meta name="description" content="CDS (Clojure Documentation Site) is a community documentation project for the Clojure programming language. It is not affiliated with
Clojure/core, does not require going through the Clojure Contributor Agreement, and is developed on GitHub.Rationale">
<meta property="og:description" content="CDS (Clojure Documentation Site) is a community documentation project for the Clojure programming language. It is not affiliated with
Clojure/core, does not require going through the Clojure Contributor Agreement, and is developed on GitHub.Rationale">
<meta property="og:url" content="https://clojure-doc.github.io/articles/about/" />
<meta property="og:title" content="About" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/about/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>About</h2>
</div>
<p>CDS (Clojure Documentation Site) is a community documentation project for the Clojure programming language. It is not affiliated with
<code>Clojure/core</code>, does not require going through the Clojure Contributor Agreement, and is developed <a href="https://github.com/clojure-doc/clojure-doc.github.io">on GitHub</a>.</p><h2 id="rationale">Rationale</h2><p>The rationale is explained in more detail in the <a href="http://blog.clojurewerkz.org/blog/2012/10/10/announcing-a-new-clojure-documentation-project/">announcement blog post</a>.</p><h2 id="history">History</h2><p>CDS was started in early October, 2012, by several active members of the Clojure community due to their dissatisfaction
with the state of documentation and documentation contribution process (that involved mailing Clojure Contributor Agreement in paper).</p><h2 id="goals">Goals</h2><p>The goal is to produce quality technical documentation for Clojure users and potential adopters with various expertise levels.</p><p>CDS strives to cover all aspects of Clojure: from tutorials and language guides to overview of the ecosystem, how
libraries are developed and published, topics operations engineers will be interested in, JVM ecosystem tools
and so on.</p><p>Adopting a language always takes more than just reading a book or a few tutorials about language features. Understanding
design goals, the ecosystem and operations is just as important. CDS will try to address this.</p><h3 id="what-cds-is-not">What CDS is Not</h3><p>What's <em>not</em> here:</p><ul><li>Cheatsheets. The official <a href="http://clojure.org/cheatsheet">Clojure cheatsheet</a> is very good. There is also an unofficial <a href="https://github.com/fogus/clojurescript-cheatsheet">ClojureScript cheatsheet</a> available for download and contribution.</li><li>API reference docs. Those can currently be found (with examples) at <a href="http://clojuredocs.org/">Clojuredocs</a>.</li></ul><p>Clojuredocs needs a lot of work and redesign (as in, the way it works) which will take a while. CDS is not concerned with providing the API reference;
only tutorials, guides, and linking to other relevant resources.</p><h2 id="structure">Structure</h2><p>CDS is structured as a number of guides. They broadly fall into 4 categories:</p><ul><li><a href="https://clojure-doc.org/articles/about/content/#clojure_tutorials">Tutorials</a></li><li><a href="https://clojure-doc.org/articles/about/content/#clojure_language_guides">Language Guides</a></li><li><a href="https://clojure-doc.org/articles/about/content/#the_clojure_ecosystem">Ecosystem &amp; Tools</a></li><li><a href="https://clojure-doc.org/articles/about/content/#cookbooks">Cookbooks</a></li></ul><h3 id="tutorials">Tutorials</h3><p>These guides are for complete newcomers and should include a lot of hand holding. They don't assume any
previous familiarity with Clojure, the JVM, the JVM tool ecosystem, functional programming, immutability, and so on.</p><p>Target audience: newcomers to the language.</p><h3 id="language-guides">Language guides</h3><p>These guides are more in-depth, focused on various aspects of the language and interoperability.
Examples of such guides include:</p><ul><li>Sequences</li><li>Interoperability</li><li>Reference types</li><li>Laziness</li><li>Macros and compilation</li></ul><p>Target audience: from developers who already have some familiarity with the language to those who have been using it for
a while.</p><h3 id="tools--ecosystem-guides">Tools &amp; Ecosystem guides</h3><p>These guides cover key Clojure ecosystem tools such as <a href="http://leiningen.org">Leiningen</a>, <a href="http://clojars.org">Clojars</a>, <a href="https://github.com/trptcolin/reply">REPLy</a>,
<a href="https://github.com/clojure/tools.nrepl">nREPL</a>, <a href="https://github.com/technomancy/clojure-mode">Emacs clojure-mode</a>, VimClojure, <a href="https://code.google.com/p/counterclockwise/">Counterclockwise</a>, <a href="http://plugins.jetbrains.com/plugin?pluginId=4050">La Clojure</a>, etc. It also covers important ecosystem projects that are not tools: books,
<a href="http://www.clojuresphere.com/">ClojureSphere</a>, <a href="http://clojurewerkz.org/">ClojureWerkz</a>, <a href="https://github.com/flatland">Flatland</a> and so on.</p><p>Target audience: all developers using or interested in the Clojure programming language.</p><h3 id="cookbooks">Cookbooks</h3><p>Concise <a href="https://clojure-doc.org/articles/about/content/#cookbooks">Clojure example code</a>, categorized by subject.</p><h2 id="mailing-list">Mailing List</h2><p>CDS <a href="https://groups.google.com/group/clojure">currently uses Clojure mailing list</a> for discussions. Feel free to join it and ask any questions you may have.</p><h2 id="news--announcements">News &amp; Announcements</h2><p>News and announcements are posted primarily on the <a href="https://clojurians.slack.com/archives/C8NUSGWG6">Clojurians Slack <code>#news-and-articles</code> channel</a>.</p><h2 id="reporting-issues">Reporting Issues</h2><p>If you find a mistake, poor grammar, an important topic not covered, or an outdated example, please <a href="https://github.com/clojure-doc/clojure-doc.github.io/issues">file an issue</a> on Github.</p><h2 id="contributing">Contributing</h2><p>CDS uses <a href="http://cryogenweb.org/">Cryogen</a>. All tutorials and guides are written in Markdown.</p><p>The toolchain and setup process are described <a href="https://github.com/clojure-doc/clojure-doc.github.io/blob/main/README.md#toolchain">in the README</a>.</p><p>To submit changes, create a branch and make your changes on it. Once you are done with your changes and all tests pass, submit a pull request
on GitHub.</p>
<div id="prev-next">
<a href="../content/index.html">Table of Contents &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="index.html">About</a></li>
<li><a href="../content/index.html">Table of Contents</a></li>
<li><a href="../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,208 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Data Structures (Help wanted)</title>
<meta name="description" content="Help wantedPlease follow the instructions on how to contribute and start writing over here">
<meta property="og:description" content="Help wantedPlease follow the instructions on how to contribute and start writing over here">
<meta property="og:url" content="https://clojure-doc.github.io/articles/cookbooks/data_structures/" />
<meta property="og:title" content="Data Structures (Help wanted)" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/cookbooks/data_structures/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Data Structures (Help wanted)</h2>
</div>
<h2 id="help-wanted">Help wanted</h2><p>Please follow the <a href="https://github.com/clojure-doc/clojure-doc.github.io/tree/source#how-to-contribute">instructions</a> on how to contribute and start writing over <a href="https://github.com/clojure-doc/clojure-doc.github.io/blob/source/content/md/articles/cookbooks/data_structures.md">here</a></p><p>This cookbook covers working with core Clojure data structures.</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p>
<div id="prev-next">
<a href="../../ecosystem/books/index.html">&laquo; Books about Clojure and ClojureScript</a>
||
<a href="../strings/index.html">Strings &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="index.html">Data Structures (Help wanted)</a></li>
<li><a href="../strings/index.html">Strings</a></li>
<li><a href="../math/index.html">Mathematics with Clojure</a></li>
<li><a href="../date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,208 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Date and Time (Help wanted)</title>
<meta name="description" content="Help wantedPlease follow the instructions on how to contribute and start writing over here">
<meta property="og:description" content="Help wantedPlease follow the instructions on how to contribute and start writing over here">
<meta property="og:url" content="https://clojure-doc.github.io/articles/cookbooks/date_and_time/" />
<meta property="og:title" content="Date and Time (Help wanted)" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/cookbooks/date_and_time/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Date and Time (Help wanted)</h2>
</div>
<h2 id="help-wanted">Help wanted</h2><p>Please follow the <a href="https://github.com/clojure-doc/clojure-doc.github.io/tree/source#how-to-contribute">instructions</a> on how to contribute and start writing over <a href="https://github.com/clojure-doc/clojure-doc.github.io/blob/source/content/md/articles/cookbooks/date_and_time.md">here</a></p><p>This cookbook covers working with date and time values in Clojure.</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p>
<div id="prev-next">
<a href="../math/index.html">&laquo; Mathematics with Clojure</a>
||
<a href="../files_and_directories/index.html">Working with Files and Directories in Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../strings/index.html">Strings</a></li>
<li><a href="../math/index.html">Mathematics with Clojure</a></li>
<li><a href="index.html">Date and Time (Help wanted)</a></li>
<li><a href="../files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,252 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Working with Files and Directories in Clojure</title>
<meta name="description" content="This cookbook covers working with files and directories from Clojure,
using functions in the clojure.java.io namespace as well as parts of
the JDK via interoperability.This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.">
<meta property="og:description" content="This cookbook covers working with files and directories from Clojure,
using functions in the clojure.java.io namespace as well as parts of
the JDK via interoperability.This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/cookbooks/files_and_directories/" />
<meta property="og:title" content="Working with Files and Directories in Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/cookbooks/files_and_directories/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Working with Files and Directories in Clojure</h2>
</div>
<p>This cookbook covers working with files and directories from Clojure,
using functions in the <code>clojure.java.io</code> namespace as well as parts of
the JDK via interoperability.</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="preliminaries">Preliminaries</h2><p>Note that for the examples below, "io" is an alias for
<code>clojure.java.io</code>. That is, it's assumed your <code>ns</code> macro contains:</p><pre><code class="clojure">(:require [clojure.java.io :as io])
</code></pre><p>or else in the repl you've loaded it:</p><pre><code class="clojure">(require '[clojure.java.io :as io])
</code></pre><h2 id="recipes">Recipes</h2><h3 id="read-a-file-into-one-long-string">Read a file into one long string</h3><pre><code class="clojure">(def a-long-string (slurp "foo.txt"))
</code></pre><p>Note, you can pass urls to <code>slurp</code> as well. See also <a href="http://clojuredocs.org/clojure_core/clojure.core/slurp">slurp at
Clojuredocs</a>.</p><h3 id="read-a-file-one-line-at-a-time">Read a file one line at a time</h3><p>Suppose you'd like to call <code>my-func</code> on every line in a file,
and return the resulting sequence:</p><pre><code class="clojure">(with-open [rdr (io/reader "foo.txt")]
(doall (map my-func (line-seq rdr))))
</code></pre><p>The <code>doall</code> is needed because the <code>map</code> call is lazy. The lines that
<code>line-seq</code> gives you have no trailing newlines (and empty lines in the
file will yield empty strings ("")).</p><h3 id="write-a-long-string-out-to-a-new-file">Write a long string out to a new file</h3><pre><code class="clojure">(spit "foo.txt"
"A long
multi-line string.
Bye.")
</code></pre><p>Overwrites the file if it already exists. To append, use</p><pre><code class="clojure">(spit "foo.txt" "file content" :append true)
</code></pre><h3 id="write-a-file-one-line-at-a-time">Write a file one line at a time</h3><p>Suppose you'd like to write out every item in a vector, one item per
line:</p><pre><code class="clojure">(with-open [wrtr (io/writer "foo.txt")]
(doseq [i my-vec]
(.write wrtr (str i "\n"))))
</code></pre><h3 id="check-if-a-file-exists">Check if a file exists</h3><pre><code class="clojure">(.exists (io/file "filename.txt"))
</code></pre><p>Is it a directory? :</p><pre><code class="clojure">(.isDirectory (io/file "path/to/something"))
</code></pre><p>An io/file is a java.io.File object (a file or a directory). You can
call a number of functions on it, including:</p><pre><code>exists Does the file exist?
isDirectory Is the File object a directory?
getName The basename of the file.
getParent The dirname of the file.
getPath Filename with directory.
mkdir Create this directory on disk.
</code></pre><p>To read about more available methods, see <a href="http://docs.oracle.com/javase/7/docs/api/java/io/File.html">the java.io.File
docs</a>.</p><h3 id="get-a-list-of-the-files-and-dirs-in-a-given-directory">Get a list of the files and dirs in a given directory</h3><p>As <code>File</code> objects:</p><pre><code class="clojure">(.listFiles (io/file "path/to/some-dir"))
</code></pre><p>Same, but just the <em>names</em> (strings), not File objects:</p><pre><code class="clojure">(.list (io/file "path/to/some-dir"))
</code></pre><p>The results of those calls are seqable.</p><h2 id="see-also">See also</h2><ul><li><a href="https://github.com/Raynes/fs">https://github.com/Raynes/fs</a></li><li>the I/O section of the <a href="http://clojure.org/cheatsheet">cheatsheet</a></li></ul>
<div id="prev-next">
<a href="../date_and_time/index.html">&laquo; Date and Time (Help wanted)</a>
||
<a href="../middleware/index.html">Middleware in Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../strings/index.html">Strings</a></li>
<li><a href="../math/index.html">Mathematics with Clojure</a></li>
<li><a href="../date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,252 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Mathematics with Clojure</title>
<meta name="description" content="This cookbook covers working with mathematics in Clojure, using
built-in functions, contrib libraries, and parts of the JDK via
interoperability.This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.">
<meta property="og:description" content="This cookbook covers working with mathematics in Clojure, using
built-in functions, contrib libraries, and parts of the JDK via
interoperability.This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/cookbooks/math/" />
<meta property="og:title" content="Mathematics with Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/cookbooks/math/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Mathematics with Clojure</h2>
</div>
<p>This cookbook covers working with mathematics in Clojure, using
built-in functions, contrib libraries, and parts of the JDK via
interoperability.</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="preliminaries">Preliminaries</h2><p>Some examples herein make use of the
<a href="https://github.com/clojure/math.numeric-tower">math.numeric-tower</a>
and
<a href="https://github.com/clojure/math.combinatorics">math.combinatorics</a>
contrib libraries. It's assumed that either you have the following in
your source code's <code>ns</code> macro:</p><pre><code class="clojure">(:require [clojure.math.numeric-tower :as math]
[clojure.math.combinatorics :as combo])
</code></pre><p>or else in the repl you've loaded them like so:</p><pre><code class="clojure">(require '[clojure.math.numeric-tower :as math])
(require '[clojure.math.combinatorics :as combo])
</code></pre><h2 id="recipes">Recipes</h2><h3 id="simple-math">Simple Math</h3><pre><code class="clojure">(+ 3 4) ;=&gt; 7
(- 3 4) ;=&gt; -1
(* 3 4) ;=&gt; 12
(/ 3 4) ;=&gt; 3/4 (an exact ratio)
(/ 3.0 4) ;=&gt; 0.75
(inc 5) ;=&gt; 6
(dec 5) ;=&gt; 4
</code></pre><p>For doing integer division and getting remainders (modulus), see the
docs for
<a href="http://clojuredocs.org/clojure_core/clojure.core/quot">quot</a>,
<a href="http://clojuredocs.org/clojure_core/clojure.core/rem">rem</a>, and
<a href="http://clojuredocs.org/clojure_core/clojure.core/mod">mod</a>.</p><p>For exponents, square roots, rounding, ceiling, floor, absolute value,
and greatest/least common multiples, see the <a href="http://clojure.github.com/math.numeric-tower/">docs for
math.numeric-tower</a>.</p><h3 id="trigonometry">Trigonometry</h3><p>Use what the Java platform provides, for example:</p><pre><code class="clojure">Math/PI ;=&gt; 3.14159...
(Math/sin x)
(Math/cos x)
(Math/tan x)
</code></pre><p>There are many more functions available, which you can read about in
the <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html">docs for
java.lang.Math</a>.</p><h3 id="combinatorics">Combinatorics</h3><p>For combinatoric functions (such as <code>combinations</code> and
<code>permutations</code>), see the <a href="http://clojure.github.com/math.combinatorics/">docs for
math.combinatorics</a>.</p>
<div id="prev-next">
<a href="../strings/index.html">&laquo; Strings</a>
||
<a href="../date_and_time/index.html">Date and Time (Help wanted) &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../strings/index.html">Strings</a></li>
<li><a href="index.html">Mathematics with Clojure</a></li>
<li><a href="../date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,326 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Middleware in Clojure</title>
<meta name="description" content="This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.What is Middleware?">
<meta property="og:description" content="This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.What is Middleware?">
<meta property="og:url" content="https://clojure-doc.github.io/articles/cookbooks/middleware/" />
<meta property="og:title" content="Middleware in Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/cookbooks/middleware/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Middleware in Clojure</h2>
</div>
<p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="what-is-middleware">What is Middleware?</h2><p>Middleware in Clojure is a common design pattern for threading a
<em>request</em> through a series of functions designed to operate on it as
well as threading the <em>response</em> through the same series of functions.</p><p>Middleware is used in many Clojure projects such as
<a href="https://github.com/mmcgrana/ring">Ring</a>,
<a href="https://github.com/dakrone/clj-http">clj-http</a> and
<a href="https://clojure-doc.org/articles/cookbooks/middleware/TODO">something else here</a>.</p><h2 id="the-client-function">The <code>client</code> function</h2><p>The base of all middleware in Clojure is the <code>client</code> function, which
takes a request object (usually a Clojure map) and returns a response
object (also usually a Clojure map).</p><p>For example, let's use a <code>client</code> function that pulls some keys out of
a map request and does an HTTP GET on a site:</p><pre><code class="clojure">(ns middleware.example
(:require [clj-http.client :as http]))
(defn client [request]
(http/get (:site request) (:options request)))
</code></pre><p>To use the client method, call it like so (response shortened to fit
here):</p><pre><code class="clojure">(client {:site "http://www.aoeu.com" :options {}})
;; ⇒ {:status 200, :headers {...}, :request-time 3057, :body "..."}
</code></pre><p>Now that a client function exists, middleware can be wrapped around it
to change the <em>request</em>, the <em>response</em>, or both.</p><p>Let's start with a middleware function that doesn't do anything. We'll
call it the <code>no-op</code> middleware:</p><pre><code class="clojure">;; It is standard convention to name middleware wrap-&lt;something&gt;
(defn wrap-no-op
;; the wrapping function takes a client function to be used...
[client-fn]
;; ...and returns a function that takes a request...
(fn [request]
;; ...that calls the client function with the request
(client-fn request)))
</code></pre><p>So how is this middleware used? First, it must be 'wrapped' around the
existing client function:</p><pre><code class="clojure">(def new-client (wrap-no-op client))
;; Now new-client can be used just like the client function:
(new-client {:site "http://www.aoeu.com" :options {}})
;; ⇒ {:status 200, :headers {...}, :request-time 3057, :body "..."}
</code></pre><p>It works! Now it's not very exiting because it doesn't do anything
yet, so let's add another middleware wrapper that does something more
exiting.</p><p>Let's add a middleware function that automatically changes all "HTTP"
requests into "HTTPS" requests. Again, we need a function that returns
another function, so we can end up with a new method to call:</p><pre><code class="clojure">(defn wrap-https
[client-fn]
(fn [request]
(let [site (:site request)
new-site (.replaceAll site "http:" "https:")
new-request (assoc request :site new-site)]
(client-fn new-request))))
</code></pre><p>The <code>wrap-https</code> middleware can be tested again by creating a new
client function:</p><pre><code class="clojure">(def https-client (wrap-https client))
;; Notice the :trace-redirects key shows that HTTPS was used instead
;; of HTTP
(https-client {:site "http://www.google.com" :options {}})
;; ⇒ {:trace-redirects ["https://www.google.com"],
;; :status 200,
;; :headers {...},
;; :request-time 3057,
;; :body "..."}
</code></pre><p>Middleware can be tested independently of the client function by
providing the identity function (or any other function that returns a
map). For example, we can see the <code>wrap-https</code> middleware returns the
clojure map with the :site changed from 'http' to 'https':</p><pre><code class="clojure">((wrap-https identity) {:site "http://www.example.com"})
;; ⇒ {:site "https://www.example.com"}
</code></pre><h2 id="combining-middleware">Combining middleware</h2><p>In the previous example, we showed how to create and use middleware,
but what about using multiple middleware functions? Let's define one
more middleware so we have a total of three to work with. Here's the
source for a middleware function that adds the current data to the
response map:</p><pre><code class="clojure">(defn wrap-add-date
[client]
(fn [request]
(let [response (client request)]
(assoc response :date (java.util.Date.)))))
</code></pre><p>And again, we can test it without using any other functions using
<code>identity</code> as the client function:</p><pre><code class="clojure">((wrap-add-date identity) {})
;; ⇒ {:date #inst "2012-11-09T12:41:05.171-00:00"}
</code></pre><p>Middleware is useful on its own, but where it becomes truly more
useful is in combining middleware together. Here's what a new client
function looks like combining all the middleware:</p><pre><code class="clojure">(def my-client (wrap-add-date (wrap-https (wrap-no-op client))))
(my-client {:site "http://www.google.com"})
;; ⇒ {:date #inst "2012-11-09T12:43:39.451-00:00",
;; :cookies {...},
;; :trace-redirects ["https://www.google.com/"],
;; :request-time 1634,
;; :status 200,
;; :headers {...},
;; :body "..."}
</code></pre><p>(The response map has been edited to take less space where you see
'...')</p><p>Here we can see that the <code>wrap-https</code> middleware has successfully
turned the request for http://www.google.com into one for
https://www.google.com, additionally the <code>wrap-add-date</code> middleware
has added the :date key with the date the request happened. (the
<code>wrap-no-op</code> middleware did execute, but since it didn't do anything,
there's no output to tell)</p><p>This is a good start, but adding middleware can be expressed in a much
cleaner and clearer way by using Clojure's threading macro, <code>-&gt;</code>. The
<code>my-client</code> definition from above can be expressed like this:</p><pre><code class="clojure">(def my-client
(-&gt; client
wrap-no-op
wrap-https
wrap-add-date))
(my-client {:site "http://www.google.com"})
;; ⇒ {:date #inst "2012-11-09T12:47:32.130-00:00",
;; :cookies {...},
;; :trace-redirects ["https://www.google.com/"],
;; :request-time 1630,
;; :status 200,
;; :headers {...},
;; :body "..."}
</code></pre><p>Something else to keep in mind is that middleware expressed in this
way will be executed <em>from the bottom up</em>, so in this case,
<code>wrap-add-date</code> will call <code>wrap-https</code>, which in turn calls
<code>wrap-no-op</code>, which finally calls the <code>client</code> function.</p><p>For an example of combining a large amount of middleware, see
<a href="https://github.com/dakrone/clj-http/blob/5534950b5ed48e3bc7285f0e956444ea832399da/src/clj_http/client.clj#L542-567">clj-http's
client.clj</a>
file</p>
<div id="prev-next">
<a href="../files_and_directories/index.html">&laquo; Working with Files and Directories in Clojure</a>
||
<a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../strings/index.html">Strings</a></li>
<li><a href="../math/index.html">Mathematics with Clojure</a></li>
<li><a href="../date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,464 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Strings</title>
<meta name="description" content="This cookbook covers working with strings in Clojure using built-in
functions, standard and contrib libraries, and parts of the JDK via
interoperability.This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.">
<meta property="og:description" content="This cookbook covers working with strings in Clojure using built-in
functions, standard and contrib libraries, and parts of the JDK via
interoperability.This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/cookbooks/strings/" />
<meta property="og:title" content="Strings" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/cookbooks/strings/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Strings</h2>
</div>
<p>This cookbook covers working with strings in Clojure using built-in
functions, standard and contrib libraries, and parts of the JDK via
interoperability.</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="overview">Overview</h2><ul><li>Strings are <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html">plain Java
strings</a>.
You can use anything which operates on them.</li><li>Java strings are immutable, so they're convenient to use in Clojure.</li><li>You can't add metadata to Java strings.</li><li>Clojure supports some convenient notations:</li></ul><pre><code> "foo" java.lang.String
#"\d" java.util.regex.Pattern (in this case, one which matches a single digit)
\f java.lang.Character (in this case, the letter 'f')
</code></pre><ul><li><strong>Caveat:</strong> Human brains and electronic computers are rather different
devices. So Java strings (sequences of <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#unicode">UTF-16
characters</a>)
don't always map nicely to user-perceived characters. For example, a
single Unicode "code point" doesn't necessarily equal a user-perceived
character. (Like Korean Hangul Jamo, where user-perceived characters
are composed from two or three Unicode code points.) Also, a Unicode
code point may sometimes require 2 UTF-16 characters to encode it.</li></ul><h2 id="preliminaries">Preliminaries</h2><p>Some examples use
<a href="http://clojure.github.io/clojure/clojure.string-api.html">clojure.string</a>,
<a href="https://github.com/edn-format/edn">clojure.edn</a> and
<a href="http://clojure.github.io/clojure/clojure.pprint-api.html">clojure.pprint</a>. We'll
assume your <code>ns</code> macro contains:</p><pre><code class="clojure">(:require [clojure.string :as str]
[clojure.edn :as edn]
[clojure.pprint :as pp])
</code></pre><p>or else in the repl you've loaded it:</p><pre><code class="clojure">(require '[clojure.string :as str])
(require '[clojure.edn :as edn])
(require '[clojure.pprint :as pp])
</code></pre><h2 id="recipes">Recipes</h2><h3 id="basics">Basics</h3><pre><code class="clojure">;; Size measurements
(count "0123") ;=&gt; 4
(empty? "0123") ;=&gt; false
(empty? "") ;=&gt; true
(str/blank? " ") ;=&gt; true
;; Concatenate
(str "foo" "bar") ;=&gt; "foobar"
(str/join ["0" "1" "2"]) ;=&gt; "012"
(str/join "." ["0" "1" "2"]) ;=&gt; "0.1.2"
;; Matching using plain Java methods.
;;
;; You might prefer regexes for these. For instance, failure returns
;; -1, which you have to test for. And characters like \o are
;; instances of java.lang.Character, which you may have to convert to
;; int or String.
(.indexOf "foo" "oo") ;=&gt; 1
(.indexOf "foo" "x") ;=&gt; -1
(.lastIndexOf "foo" (int \o)) ;=&gt; 2
;; Substring
(subs "0123" 1) ;=&gt; "123"
(subs "0123" 1 3) ;=&gt; "12"
(str/trim " foo ") ;=&gt; "foo"
(str/triml " foo ") ;=&gt; "foo "
(str/trimr " foo ") ;=&gt; " foo"
;; Multiple substrings
(seq "foo") ;=&gt; (\f \o \o)
(str/split "foo/bar/quux" #"/") ;=&gt; ["foo" "bar" "quux"]
(str/split "foo/bar/quux" #"/" 2) ;=&gt; ["foo" "bar/quux"]
(str/split-lines "foo
bar") ;=&gt; ["foo" "bar"]
;; Case
(str/lower-case "fOo") ;=&gt; "foo"
(str/upper-case "fOo") ;=&gt; "FOO"
(str/capitalize "fOo") ;=&gt; "Foo"
;; Escaping
(str/escape "foo|bar|quux" {\| "||"}) ;=&gt; "foo||bar||quux"
;; Get byte array of given encoding.
;; (The output will likely have a different number than "3c3660".)
(.getBytes "foo" "UTF-8") ;=&gt; #&lt;byte[] [B@3c3660&gt;
;; Parsing keywords
(keyword "foo") ;=&gt; :foo
;; Parsing numbers
(bigint "20000000000000000000000000000") ;=&gt; 20000000000000000000000000000N
(bigdec "20000000000000000000.00000000") ;=&gt; 20000000000000000000.00000000M
(Integer/parseInt "2") ;=&gt; 2
(Float/parseFloat "2") ;=&gt; 2.0
;; Parsing edn, a subset of Clojure forms.
(edn/read-string "0xffff") ;=&gt; 65535
;; The sledgehammer approach to reading Clojure forms.
;;
;; SECURITY WARNING: Ensure *read-eval* is false when dealing with
;; strings you don't 100% trust. Even though *read-eval* is false by
;; default since Clojure 1.5, be paranoid and set it to false right
;; before you use it, because anything could've re-bound it to true.
(binding [*read-eval* false]
(read-string "#\"[abc]\""))
;=&gt; #"[abc]"
</code></pre><h3 id="parsing-complex-strings">Parsing complex strings</h3><h4 id="regexes">Regexes</h4><p>Regexes offer a boost in string-matching power. You can express ideas
like repetition, alternatives, etc.</p><p><a href="http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html">Regex
reference.</a></p><p><strong>Groups:</strong> Regex groups are useful, when we want to match more than
one substring. (Or refer to matches later.) In the regex <code>#"(group-1) (group-2)"</code>, the 0th group is the whole match. The 1st group is
started by the left-most <code>(</code>, the 2nd group is started by the
second-left-most <code>(</code>, etc. You can even nest groups. You can refer to
groups later using <code>$0</code>, <code>$1</code>, etc.</p><p><strong>Matching</strong></p><pre><code class="clojure">;; Simple matching
(re-find #"\d+" "foo 123 bar") ;=&gt; "123"
;; What happens when a match fails.
(re-find #"\d+" "foobar") ;=&gt; nil
;; Return only the first groups which satisfy match.
(re-matches #"(@\w+)\s([.0-9]+)%"
"@shanley 19.8%")
;=&gt;["@shanley 19.8%" "@shanley" "19.8"]
;; Return seq of all matching groups which occur in string.
(re-seq #"(@\w+)\s([.0-9]+)%"
"@davidgraeber 12.3%,@shanley 19.8%")
;=&gt; (["@davidgraeber 12.3%" "@davidgraeber" "12.3"]
; ["@shanley 19.8%" "@shanley" "19.8"])
</code></pre><p><strong>Replacing</strong></p><p>We use <code>str/replace</code>. Aside from the first arg (the initial string),
the next two args are match and replacement:</p><pre><code> match / replacement can be:
string / string
char / char
pattern / (string or function of match).
</code></pre><pre><code class="clojure">;; In the replacement string, $0, $1, etc refer to matched groups.
(str/replace "@davidgraeber 12.3%,@shanley 19.8%"
#"(@\S+)\s([.0-9]+)%"
"$2 ($1)")
;=&gt; "12.3 (@davidgraeber),19.8 (@shanley)"
;; Using a function to replace text gives us power.
(println
(str/replace "@davidgraeber 12.3%,@shanley 19.8%"
#"(@\w+)\s([.0-9]+)%,?"
(fn [[_ person percent]]
(let [points (-&gt; percent Float/parseFloat (* 100) Math/round)]
(str person "'s followers grew " points " points.\n")))))
;print=&gt; @davidgraeber's followers grew 1230 points.
;print=&gt; @shanley's followers grew 1980 points.
;print=&gt;
</code></pre><h4 id="context-free-grammars">Context-free grammars</h4><p>Context-free grammars offer yet another boost in expressive matching
power, compared to regexes. You can express ideas like nesting.</p><p>We'll use <a href="https://github.com/Engelberg/instaparse">Instaparse</a> on
<a href="http://www.json.org/">JSON's grammar</a>. (This example isn't seriously
tested nor a featureful parser. Use
<a href="https://github.com/clojure/data.json">data.json</a> instead.)</p><pre><code class="clojure">;; Your project.clj should contain this (you may need to restart your JVM):
;; :dependencies [[instaparse "1.2.4"]]
;;
;; We'll assume your ns macro contains:
;; (:require [instaparse.core :as insta])
;; or else in the repl you've loaded it:
;; (require '[instaparse.core :as insta])
(def barely-tested-json-parser
(insta/parser
"object = &lt;'{'&gt; &lt;w*&gt; (members &lt;w*&gt;)* &lt;'}'&gt;
&lt;members&gt; = pair (&lt;w*&gt; &lt;','&gt; &lt;w*&gt; members)*
&lt;pair&gt; = string &lt;w*&gt; &lt;':'&gt; &lt;w*&gt; value
&lt;value&gt; = string | number | object | array | 'true' | 'false' | 'null'
array = &lt;'['&gt; elements* &lt;']'&gt;
&lt;elements&gt; = value &lt;w*&gt; (&lt;','&gt; &lt;w*&gt; elements)*
number = int frac? exp?
&lt;int&gt; = '-'? digits
&lt;frac&gt; = '.' digits
&lt;exp&gt; = e digits
&lt;e&gt; = ('e' | 'E') (&lt;'+'&gt; | '-')?
&lt;digits&gt; = #'[0-9]+'
(* First sketched state machine; then it was easier to figure out
regex syntax and all the maddening escape-backslashes. *)
string = &lt;'\\\"'&gt; #'([^\"\\\\]|\\\\.)*' &lt;'\\\"'&gt;
&lt;w&gt; = #'\\s+'"))
(barely-tested-json-parser "{\"foo\": {\"bar\": 99.9e-9, \"quux\": [1, 2, -3]}}")
;=&gt; [:object
; [:string "foo"]
; [:object
; [:string "bar"]
; [:number "99" "." "9" "e" "-" "9"]
; [:string "quux"]
; [:array [:number "1"] [:number "2"] [:number "-" "3"]]]]
;; That last output is a bit verbose. Let's process it further.
(-&gt;&gt; (barely-tested-json-parser "{\"foo\": {\"bar\": 99.9e-9, \"quux\": [1, 2, -3]}}")
(insta/transform {:object hash-map
:string str
:array vector
:number (comp edn/read-string str)}))
;=&gt; {"foo" {"quux" [1 2 -3], "bar" 9.99E-8}}
;; Now we can appreciate what those &lt;angle-brackets&gt; were all about.
;;
;; When to the right of the grammar's =, it totally hides the enclosed
;; thing in the output. For example, we don't care about whitespace,
;; so we hide it with &lt;w*&gt;.
;;
;; When to the left of the grammar's =, it merely prevents a level of
;; nesting in the output. For example, "members" is a rather
;; artificial entity, so we prevent a pointless level of nesting with
;; &lt;members&gt;.
</code></pre><h3 id="building-complex-strings">Building complex strings</h3><h4 id="redirecting-streams">Redirecting streams</h4><p><code>with-out-str</code> provides a simple way to build strings. It redirects
standard output (<code>*out*</code>) to a fresh <code>StringWriter</code>, then returns the
resulting string. So you can use functions like <code>print</code>, <em>even in
nested functions</em>, and get the resulting string at the end.</p><pre><code class="clojure">(let [shrimp-varieties ["shrimp-kabobs" "shrimp creole" "shrimp gumbo"]]
(with-out-str
(print "We have ")
(doseq [name (str/join ", " shrimp-varieties)]
(print name))
(print "...")))
;=&gt; "We have shrimp-kabobs, shrimp creole, shrimp gumbo..."
</code></pre><h4 id="format-strings">Format strings</h4><p>Java's templating mini-language helps you build many strings
conveniently. <a href="http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html">Reference.</a></p><pre><code class="clojure">;; %s is most commonly used to print args. Escape %'s with %%.
(format "%s enjoyed %s%%." "Mozambique" 19.8) ;=&gt; "Mozambique enjoyed 19.8%."
;; The 1$ prefix allows you to keep referring to the first arg.
(format "%1$tY-%1$tm-%1$td" #inst"2000-01-02T00:00:00") ;=&gt; "2000-01-02"
;; Again, 1$, 2$, etc prefixes let us refer to args in arbitrary orders.
(format "New year: %2$tY. Old year: %1$tY"
#inst"2000-01-02T00:00:00"
#inst"3111-12-31T00:00:00")
;=&gt; "New year: 3111. Old year: 2000"
</code></pre><h4 id="cl-format">CL-Format</h4><p><code>cl-format</code> is a port of Common Lisp's notorious, powerful string
formatting mini-language. For example, you can build strings from
sequences. (As well as oddities like print numbers in English or two
varieties of Roman numerals.) However, it's weaker than plain <code>format</code>
with printing dates and referring to args in arbitrary order.</p><p>Remember that <code>cl-format</code> represents a (potentially unreadable)
language which your audience didn't sign up to learn. If you're the
sort of person who likes it, try to only use it in sweetspots where it
provides clarity for little complexity.</p><p><a href="http://www.gigamonkeys.com/book/a-few-format-recipes.html">Tutorial</a>
in Practical Common
Lisp. <a href="http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm">Reference</a>
in Common Lisp's Hyperspec.</p><pre><code class="clojure">;; The first param prints to *out* if true. To string if false.
;; To a stream if it's a stream.
(pp/cl-format true "~{~{~a had ~s percentage point~:p.~}~^~%~}"
{"@davidgraeber" 12.3
"@shanley" 19.8
"@tjgabbour" 1})
;print=&gt; @davidgraeber had 12.3 percentage points.
;print=&gt; @tjgabbour had 1 percentage point.
;print=&gt; @shanley had 19.8 percentage points.
(def format-string "~{~#[~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~}")
(pp/cl-format nil format-string [])
;=&gt; ""
(pp/cl-format nil format-string ["@shanley"])
;=&gt; "@shanley"
(pp/cl-format nil format-string ["@shanley", "@davidgraeber"])
;=&gt; "@shanley and @davidgraeber"
(pp/cl-format nil format-string ["@shanley", "@davidgraeber", "@sarahkendzior"])
;=&gt; "@shanley, @davidgraeber, and @sarahkendzior"
</code></pre><h2 id="contributors">Contributors</h2><p>Tj Gabbour <a href="mailto:tjg@simplevalue.de">tjg@simplevalue.de</a>, 2013 (original author)</p>
<div id="prev-next">
<a href="../data_structures/index.html">&laquo; Data Structures (Help wanted)</a>
||
<a href="../math/index.html">Mathematics with Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="index.html">Strings</a></li>
<li><a href="../math/index.html">Mathematics with Clojure</a></li>
<li><a href="../date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,213 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Clojure Community</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/community/" />
<meta property="og:title" content="Clojure Community" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/community/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Clojure Community</h2>
</div>
<p>This guide covers:</p><ul><li>The Official Clojure mailing lists</li><li>IRC channel</li><li>Documentation sites</li><li>Clojure User Groups around the globe</li><li>Conferences about or related to Clojure</li><li>Various Community sites about Clojure (subreddit, etc)</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="clojure-mailing-lists">Clojure Mailing Lists</h2><ul><li><a href="https://groups.google.com/forum/?fromgroups#!forum/clojure">Clojure user mailing list</a></li><li><a href="https://groups.google.com/forum/?fromgroups#!forum/clojure-dev">Clojure development mailing list</a></li></ul><h2 id="clojure-irc-channels">Clojure IRC Channels</h2><h3 id="main-channel">Main Channel</h3><p><code>#clojure</code> on <code>irc.freenode.net</code>.</p><p>Channel logs are available at <a href="http://clojure-log.n01se.net/">clojure-log.n01se.net</a> and <a href="http://www.raynes.me/logs/irc.freenode.net/clojure/">www.raynes.me/logs/irc.freenode.net/clojure/</a>.</p><h3 id="documentation-channel">Documentation Channel</h3><p><code>#clojure-doc</code> on <code>irc.freenode.net</code>.</p><h2 id="documentation">Documentation</h2><ul><li><a href="http://clojuredocs.org/">Clojuredocs</a>: Clojure API reference, with examples</li><li><a href="http://jafingerhut.github.io/cheatsheet/clojuredocs/cheatsheet-tiptip-no-cdocs-summary.html">Clojure API Cheatsheet</a></li><li><a href="http://clojurekoans.com/">Clojure Koans</a></li><li><a href="http://www.getclojure.org">GetClojure</a>: Tens of thousands of searchable Clojure examples mined from all over the internet.</li><li><a href="http://grimoire.arrdem.com/">Grimoire</a></li></ul><h2 id="courses">Courses</h2><ul><li><a href="http://www.udemy.com/clojure-code">Udemy's 19 part series on Clojure</a></li><li><a href="http://mooc.cs.helsinki.fi/clojure">Functional Programming with Clojure</a></li></ul><h2 id="user-groups">User Groups</h2><ul><li>The list of <a href="../user_groups/index.html">Clojure User Groups</a> around the world</li><li><a href="../running_cljug/index.html">How to run your own Clojure User Group</a></li></ul><h2 id="videos-about-clojure">Videos About Clojure</h2><p>Videos of talks about Clojure are often made available on <a href="http://www.infoq.com/clojure">InfoQ</a>, and <a href="https://www.youtube.com/user/ClojureTV">Clojure YouTube channel</a>.</p><ul><li><a href="http://vimeo.com/channels/fulldisclojure/videos">Full Disclojure</a> is a series of screencasts about Clojure</li><li><a href="http://pluralsight.com/training/Courses/TableOfContents/clojure-concurrency-tutorial">Clojure Concurrency Tutorial</a></li><li><a href="http://shop.oreilly.com/product/0636920030409.do">Clojure Inside Out</a> from O'Reilly</li><li><a href="http://www.youtube.com/playlist?list=PL1p6TgkbKXqyOwq6iSkce_EY5YWFHciHt">Clojure Koans Walkthroughs</a></li><li><a href="http://pluralsight.com/training/courses/TableOfContents?courseName=clojure-fundamentals-part-one">Clojure Fundamentals</a></li><li><a href="http://www.purelyfunctional.tv/">LispCast</a></li><li><a href="https://tbaldridge.pivotshare.com/">Clojure Tutorials by Tim Baldridge</a></li></ul><h2 id="podcasts-about-clojure">Podcasts About Clojure</h2><ul><li><a href="http://mostlylazy.com/">Mostly λazy… a Clojure podcast</a> by Chas Emerick</li><li><a href="http://cognitect.com/podcast">Cognicast</a> by Craig Andera often discusses topics relevant to Clojure and ClojureScript.</li></ul><h2 id="code-repositories">Code Repositories</h2><p>Most folks host their projects at
<a href="https://github.com/languages/Clojure">GitHub</a>, and most pure Clojure
library distributions (with the exception of contrib) are available at
<a href="https://clojars.org/">Clojars</a>.</p><h2 id="websites">Websites</h2><ul><li><a href="http://clojure.org/">Clojure.org</a>: the official website</li><li><a href="http://planet.clojure.in/">Planet Clojure</a>: aggregator of selected Clojure-related blog posts</li><li><a href="http://rosettacode.org/wiki/Category:Clojure">Clojure at Rosetta Code</a></li><li><a href="http://dev.clojure.org/dashboard.action">Clojure Confluence wiki</a></li><li><a href="http://www.clojure-toolbox.com/">The Clojure Toolbox</a>: a categorized directory of libraries and tools for Clojure</li><li><a href="https://www.4clojure.com/">4Clojure</a>: Clojure exercise problems</li><li><a href="http://exercism.io/">Exercism.io</a>: Peer-reviewed Clojure exercises</li></ul><h2 id="forums">Forums</h2><ul><li><a href="http://www.reddit.com/r/clojure">r/Clojure subreddit</a></li></ul><h2 id="conferences">Conferences</h2><p>In no particular order:</p><ul><li><a href="http://clojure-conj.org/">Clojure/conj</a>, aka "the Conj"</li><li><a href="http://euroclojure.com/">EuroClojure</a></li><li><a href="http://clojurewest.org/">Clojure/West</a></li><li><a href="https://thestrangeloop.com/">StrangeLoop</a> (not about Clojure but often has strong Clojure community presence)</li><li><a href="http://lambdajam.com/">Lambda Jam</a> (also not about Clojure but has strong Clojure community presence)</li></ul><h2 id="email-newsletters">Email Newsletters</h2><ul><li><a href="http://www.clojuregazette.com/">Clojure Gazette</a></li><li><a href="http://defnewsletter.com/">(def newsletter)</a></li></ul><h2 id="workshops">Workshops</h2><ul><li><a href="http://www.clojurebridge.org/">ClojureBridge</a></li><li><a href="http://lambdanext.eu/">Lambda Next</a></li></ul><h2 id="core-development">Core development</h2><p>See the <a href="http://dev.clojure.org/display/design/Home">Clojure Confluence wiki</a> for full details on
how core development is handled.</p><p>Coordination of development efforts happen on the development mailing list, on the Confluence wiki,
and make use of the <a href="http://dev.clojure.org/jira/browse/CLJ">JIRA bug and issue tracker</a>.</p><p>Although Clojure and the contrib libraries all have homes <a href="https://github.com/clojure">at GitHub</a>,
<strong>pull-requests are not accepted</strong>. All core development happens via JIRA, patches and the Confluence wiki.</p>
<div id="prev-next">
<a href="../maven/index.html">&laquo; How to use Maven to build Clojure projects</a>
||
<a href="../user_groups/index.html">Clojure User Groups &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,244 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Filters</title>
<meta name="description" content="core.typed includes an implementation of occurrence typing, which helps the type
checker refine types according to control flow.Occurrence typing helps core.typed infer a very accurate type for this expression
by recognising the semantics of predicates like symbol? and number?.">
<meta property="og:description" content="core.typed includes an implementation of occurrence typing, which helps the type
checker refine types according to control flow.Occurrence typing helps core.typed infer a very accurate type for this expression
by recognising the semantics of predicates like symbol? and number?.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/filters/" />
<meta property="og:title" content="core.typed - Filters" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/filters/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Filters</h2>
</div>
<p>core.typed includes an implementation of occurrence typing, which helps the type
checker refine types according to control flow.</p><p>Occurrence typing helps core.typed infer a very accurate type for this expression
by recognising the semantics of predicates like <code>symbol?</code> and <code>number?</code>.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (let [a (ann-form 1 Any)]
(cond
(symbol? a) a
(number? a) a)))
(U clojure.lang.Symbol java.lang.Number nil)
</code></pre><h2 id="filters">Filters</h2><p>core.typed collects more information than just types for each expression.</p><p>A structure called a filter set is also inferred. A filter set is a collection
of two filters:</p><ul><li>a filter that is true if the expression is a true value, called the <code>then</code> filter</li><li>a filter that is true if the expression is a false value, called the <code>else</code> filter</li></ul><h3 id="trivial-filters">Trivial Filters</h3><p>There are two trivial filters:</p><ul><li><code>tt</code>, the trivially true filter</li><li><code>ff</code>, the impossible filter</li></ul><p>We can use <code>cf</code> to check the filters of expressions.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf 1)
[(Value 1) {:then tt, :else ff}]
</code></pre><p>The second place of the result vector is the filter set inferred for the expression.
<code>{:then tt, :else ff}</code> reads: the expression could be a true value, but it is impossible
for it to be a false value. This of course aligns with the semantics of numbers in Clojure.</p><p>False values are never true:</p><pre><code class="clojure">clojure.core.typed=&gt; (cf nil)
[nil {:then ff, :else tt}]
</code></pre><h3 id="positive-and-negative-type-filters">Positive and Negative Type Filters</h3><p>Filters can hold information relating bindings to types.</p><p>A positive type filter refines a local binding to be a type.</p><p>This filter says that the local binding <code>a</code> is of type <code>Number</code>.</p><pre><code class="clojure">(is Number a)
</code></pre><p>A negative type filter refines a local binding to <em>not</em> be a type.</p><p>This filter says that the local binding <code>a</code> is <em>not</em> of type <code>Number</code>.</p><pre><code class="clojure">(! Number a)
</code></pre><h3 id="latent-filters">Latent Filters</h3><p>Filters almost never need to be written directly in normal code. <em>Latent</em> filters
however are very useful, and provide the most useful information to core.typed.</p><p>A <em>latent filter set</em> is a filter set attached to a function type. It is latent
because it is not used directly: instead when a function with a latent filter set
is called, the filter set is instantiated in a way that makes sense in the current
context before it is used like a normal filter.</p><h3 id="predicates">Predicates</h3><p>A very common place for a latent filters are in the types for predicates.</p><p>The type for <code>symbol?</code>, is</p><pre><code class="clojure">[Any -&gt; Boolean :filters {:then (is Symbol 0), :else (! Symbol 0)}]
</code></pre><p>First, notice that latent type predicates can also take an integer as an identifier.
The <code>0</code> represents the first argument of the function the latent filter set is attached to.</p><p>So the latent <code>then</code> filter <code>(is Symbol 0)</code> says the first argument to <code>symbol?</code> is of type <code>Symbol</code>
if the whole expression is a true value. To retrieve a non-latent filter, the <code>0</code> is instantiated to
the appropriate local binding.</p><pre><code>Note: Use `clojure.core.typed/print-filterset` to print the filter set of an expression.
</code></pre><pre><code class="clojure">clojure.core.typed=&gt; (cf (let [a (ann-form 1 Any)]
(print-filterset "symbol filters"
(symbol? a))))
"symbol filters"
{:then (is clojure.lang.Symbol a), :else (! clojure.lang.Symbol a)}
empty-object
Flow tt
boolean
</code></pre><p>By printing the filter set of <code>(symbol? a)</code> we can see this in work, which
has a non-latent filter set of <code>{:then (is clojure.lang.Symbol a), :else (! clojure.lang.Symbol a)}</code>.</p><h3 id="paths-and-objects">Paths and Objects</h3><p>TODO</p>
<div id="prev-next">
<a href="../poly_fn/index.html">&laquo; core.typed - Polymorphic Functions</a>
||
<a href="../mm_protocol_datatypes/index.html">core.typed - Protocols &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,237 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Functions</title>
<meta name="description" content="Common things that are IFns:">
<meta property="og:description" content="Common things that are IFns:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/function_types/" />
<meta property="og:title" content="core.typed - Functions" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/function_types/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Functions</h2>
</div>
<ul><li>Function types are quite different from Typed Racket
<ul><li>anything can implement the <code>IFn</code> interface</li><li>In core.typed the <code>Function</code> type is more a special type than the type for lambdas</li></ul></li></ul><p>Common things that are <code>IFn</code>s:</p><pre><code class="clojure">- clojure.lang.Function
- c.l.Keyword
- [Any -&gt; Any]
- (c.l.PersistentHashMap k v)
- (All [x]
(Fn [Any -&gt; (U nil v)]
[Any x -&gt; (U x v)]))
- (c.l.PersistentHashSet v)
- (All [x]
(Fn [Any -&gt; (U nil v)]))
- c.l.Symbol
- [Any -&gt; Any]
- (Value :a)
- (All [x]
[Any -&gt; x :filters {:then (is {:a x} 0)}])
- (Value sym)
- (All [x] [Any -&gt; (U nil v)])
</code></pre><p>The <code>IFn</code> class might be parameterised by a <code>Function</code> type.
The immediate problem is intersections allows us to have more
than one function type.</p><p>eg. What function type is this?</p><pre><code class="clojure">(I (Value :a)
(All [x]
[Any -&gt; x :filters {:then (is {:a x} 0)}])
</code></pre><p>Even <code>(Value :a)</code> inherits two function types:</p><ul><li>that for c.l.Keyword</li><li>that for <code>(Value :a)</code></li></ul><p><code>(Value :a) &lt;: (IFn x)</code> infers <code>x</code> to be:</p><pre><code class="clojure">(I [Any -&gt; Any]
(All [x]
[Any -&gt; x :filters {:then (is {:a x} 0)}])
</code></pre><p>The second member of the intersection is more specific,
thus can be simplified to:</p><pre><code class="clojure">(All [x]
[Any -&gt; x :filters {:then (is {:a x} 0)}])
</code></pre><p>Does this work in general? As long as there is a subtyping relationship
between the possible <code>Function</code> types, we can infer the most useful
one.</p>
<div id="prev-next">
<a href="../loops/index.html">&laquo; core.typed - Looping constructs</a>
||
<a href="../limitations/index.html">core.typed - Limitations &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,207 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - User Documentation Home</title>
<meta name="description" content="core.typed is an optional type system for Clojure.Quickstart">
<meta property="og:description" content="core.typed is an optional type system for Clojure.Quickstart">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/home/" />
<meta property="og:title" content="core.typed - User Documentation Home" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/home/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - User Documentation Home</h2>
</div>
<p>core.typed is an optional type system for Clojure.</p><h2 id="quickstart">Quickstart</h2><p><code>(clojure.core.typed/ann v t)</code> gives var <code>v</code> the static type <code>t</code>.</p><p><code>(clojure.core.typed/ann-form f t)</code> ensures form <code>f</code> is of the static type <code>t</code>.</p><p><code>(clojure.core.typed/check-ns)</code> type checks the current namespace.</p><p><code>(clojure.core.typed/cf t)</code> type checks the form <code>t</code>.</p><p>See the <a href="../quick_guide.html">Quick Guide</a>.</p><h2 id="rationale"><a href="../rationale/index.html">Rationale</a></h2><p>Why core.typed exists, what can it do for you?</p><h2 id="getting-started-guide">Getting Started Guide</h2><p>If you are new to core.typed, gradual type systems, or even types in general, and want to learn how
core.typed can help verify your programs, start here.</p><h3 id="introduction-and-motivation"><a href="../start/introduction_and_motivation/index.html">Introduction and Motivation</a></h3><p>We discuss some theory and design goals of core.typed.</p><h3 id="annotations"><a href="../start/annotations/index.html">Annotations</a></h3><p>Where and how to annotate your code to help core.typed check your code.</p><h3 id="types"><a href="../types/index.html">Types</a></h3><p>Syntax and descriptions of core.typed types.</p><h3 id="polymorphic-functions-bounds-and-higher-kinded-variables"><a href="../poly_fn/index.html">Polymorphic Functions, Bounds and Higher-kinded Variables</a></h3><h3 id="filters"><a href="../filters/index.html">Filters</a></h3><p>An overview of filters for occurrence typing.</p><h3 id="datatypes-and-protocols"><a href="../mm_protocol_datatypes/index.html">Datatypes and Protocols</a></h3><p>Typing definitions and usages of Clojure datatypes and protocols.</p><h3 id="looping-constructs"><a href="../loops/index.html">Looping constructs</a></h3><p>core.typed provides several wrapper macros for common looping constructs.</p><h3 id="dotted-functions">Dotted Functions</h3><h3 id="java-classes-arrays-and-interop">Java Classes, Arrays and Interop</h3><h2 id="miscellaneous-tutorials">Miscellaneous Tutorials</h2><h3 id="hole-driven-development"><a href="https://github.com/clojure/core.typed/blob/master/src/test/clojure/clojure/core/typed/test/hole.clj">Hole-Driven Development</a></h3><p>A fun diversion playing with holes.</p><ul><li>Requires some knowledge of Haskell.</li></ul><h2 id="examples">Examples</h2><h3 id="irc-bot"><a href="https://github.com/frenchy64/Parjer">IRC Bot</a></h3><h2 id="limitations---known-issues"><a href="../limitations/index.html">Limitations</a> - Known issues</h2><h2 id="documentation-contributors">Documentation Contributors</h2><p>Ambrose Bonnaire-Sergeant (@ambrosebs)</p><p>Copyright 2013, Ambrose Bonnaire-Sergeant</p>
<div id="prev-next">
<a href="../../java_jdbc/reusing_connections.html">&laquo; java.jdbc - How to reuse database connections</a>
||
<a href="../user_documentation/index.html">core.typed - User Documentation &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,222 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Limitations</title>
<meta name="description" content="Namespace managementTyped dependencies NYI.">
<meta property="og:description" content="Namespace managementTyped dependencies NYI.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/limitations/" />
<meta property="og:title" content="core.typed - Limitations" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/limitations/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Limitations</h2>
</div>
<h2 id="namespace-management">Namespace management</h2><p>Typed dependencies NYI.</p><h2 id="destructuring">Destructuring</h2><p>Only map destructuring <em>without</em> options is supported.</p><p>Other forms of destructuring require equality filters.</p><h2 id="shadowing-bindings">Shadowing bindings</h2><p>If an argument is shadowed and the shadowed binding is referenced
in filters or object then the shadow is indistinguishable from the parameter
and parameter will be incorrectly abstracted.</p><p>eg.</p><pre><code class="clojure">(fn [a]
(if (= a 1)
(let [a 'foo] ; here this shadows the argument, impossible to recover filters
a) ; in fact any new filters about a will be incorrectly assumed to be the argument
false))
</code></pre><p>(See <code>abstract-result</code> in <code>typed/test.clj</code>)</p><h2 id="dotted-functions">Dotted Functions</h2><p>A dotted function contains a dotted variable in its function type.</p><p>eg. map's type:
<code>(All [c a b ...] [[a b ... b -&gt; c] (U nil (Seqable a)) (U nil (Seqable b)) ... b -&gt; (Seqable c)]))</code></p><p>We can't currently check the definitions of functions with dotted rest arguments.</p><h2 id="rest-arguments">Rest Arguments</h2><p>Currently cannot check the definition of functions with rest arguments,
but usage checking should work.</p><h2 id="using-filter">Using <code>filter</code></h2><p>Not everything can be inferred from a <code>filter</code>. A common example is
<code>(filter identity coll)</code> does not work. The reason is <code>identity</code> only
gives negative information when its result is true: that the argument is <em>not</em><code>(U nil false)</code>.</p><p>This idiom must be converted to this syntax <code>(fn [a] a)</code> and then annotated with
positive propositions.</p><pre><code class="clojure">;eg.
(filter (ann-form (fn [a] a)
[(U nil Number) -&gt; (U nil Number) :filters {:then (is Number 0)}])
[1 nil 2])
; :- (Seqable Number)
</code></pre><p>Positive information infers just fine, like <code>(filter number? coll)</code>.
The above idiom is useful when you are filtering something like a <code>(Seqable (U nil x))</code> and there is no
predicate to test for <code>x</code>, so you can only test if something isn't <code>nil</code>.</p>
<div id="prev-next">
<a href="../function_types/index.html">&laquo; core.typed - Functions</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,223 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Looping constructs</title>
<meta name="description" content="Due to limitations in core.typed&#39;s inference, we require using &quot;typed&quot; versions
of several core forms.loop">
<meta property="og:description" content="Due to limitations in core.typed&#39;s inference, we require using &quot;typed&quot; versions
of several core forms.loop">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/loops/" />
<meta property="og:title" content="core.typed - Looping constructs" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/loops/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Looping constructs</h2>
</div>
<p>Due to limitations in core.typed's inference, we require using "typed" versions
of several core forms.</p><h1 id="loop">loop</h1><p>Usages of <code>loop</code> should be replaced with <code>clojure.core.typed/loop&gt;</code>.</p><p>The syntax is identical except each loop variable requires a type annotation.</p><pre><code class="clojure">(loop&gt; [[a :- Number] 1
[b :- (U nil Number)] nil]
...)
</code></pre><h1 id="named-fns">Named fn's</h1><p>Named <code>fn</code>'s require full annotation for accurate recursive calls inside the <code>fn</code> body.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (ann-form (fn a [n] (+ (a 1) n))
[Number -&gt; Number]))
(Fn [java.lang.Number -&gt; java.lang.Number])
</code></pre><h1 id="for">for</h1><p>Use <code>clojure.core.typed/for&gt;</code> instead of <code>for</code>.</p><p><code>for&gt;</code> requires annotations for the return type of the body
of the for, and the left hand side of each binding form.</p><pre><code class="clojure">(for&gt; :- Number
[[a :- (U nil AnyInteger)] [1 nil 2 3]
:when a]
(inc a))
</code></pre><h1 id="doseq">doseq</h1><p>Use <code>clojure.core.typed/doseq&gt;</code> instead of <code>doseq</code>.</p><p><code>doseq&gt;</code> requires annotations for the left hand side of each binding form.</p><pre><code class="clojure">(doseq&gt; [[a :- (U nil AnyInteger)] [1 nil 2 3]
:when a]
(inc a))
</code></pre>
<div id="prev-next">
<a href="../mm_protocol_datatypes/index.html">&laquo; core.typed - Protocols</a>
||
<a href="../function_types/index.html">core.typed - Functions &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,219 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Protocols</title>
<meta name="description" content="Annotating Protocolsclojure.core.typed/ann-protocol annotates protocols.">
<meta property="og:description" content="Annotating Protocolsclojure.core.typed/ann-protocol annotates protocols.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/mm_protocol_datatypes/" />
<meta property="og:title" content="core.typed - Protocols" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/mm_protocol_datatypes/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Protocols</h2>
</div>
<h2 id="annotating-protocols">Annotating Protocols</h2><p><code>clojure.core.typed/ann-protocol</code> annotates protocols.</p><p>Takes a name and a optionally a :methods keyword argument mapping
method names to expected types.</p><p>Protocol definitions should use <code>clojure.core.typed/defprotocol&gt;</code> (identical syntax to <code>defprotocol</code>).</p><pre><code class="clojure">(ann-protocol IUnifyWithLVar
unify-with-lvar [Term LVar ISubstitutions -&gt; (U ISubstitutions Fail)])
(defprotocol&gt; IUnifyWithLVar
(unify-with-lvar [v u s]))
</code></pre><p>Each protocol method argument (including the first) is explicit in the type annotation.
Often, the the first argument (aka. <code>this</code>) will just be the protocol, but in some cases
it is convenient to add more general types.</p><h2 id="annotating-datatypes">Annotating datatypes</h2><p><code>clojure.core.typed/ann-datatype</code> annotates datatypes.</p><p>Takes a name and a vector of fieldname/type type entries.</p><pre><code class="clojure">(ann-datatype Pair [lhs :- Term
rhs :- Term])
(deftype Pair [lhs rhs]
...)
</code></pre><p>Each protocol extended in <code>deftype</code> must have an annotated expected type with <code>ann-protocol</code>.</p><p>The types for Java interface method are inferred from their corresponding Java type.</p>
<div id="prev-next">
<a href="../filters/index.html">&laquo; core.typed - Filters</a>
||
<a href="../loops/index.html">core.typed - Looping constructs &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,234 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Polymorphic Functions</title>
<meta name="description" content="core.typed supports polymorphic function types. They allow us to specify
function types which are both general and accurate.All">
<meta property="og:description" content="core.typed supports polymorphic function types. They allow us to specify
function types which are both general and accurate.All">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/poly_fn/" />
<meta property="og:title" content="core.typed - Polymorphic Functions" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/poly_fn/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Polymorphic Functions</h2>
</div>
<p>core.typed supports polymorphic function types. They allow us to specify
function types which are both general and accurate.</p><h1 id="all">All</h1><p>The primitive <code>All</code> constructor creates a polymorphic binder and scopes
type variables in a type.</p><p>The identity function has a simple polymorphic type:</p><pre><code class="clojure">(All [x]
[x -&gt; x])
</code></pre><p>Read: for all types <code>x</code>, a function that takes an <code>x</code> and returns an <code>x</code>.</p><p>Polymorphic types are introduced with annotations, but where are they eliminated?
We use local type inference to infer type variable types based on how they are used.</p><pre><code class="clojure">(identity :a)
</code></pre><p>In the above example, we infer <code>x</code> to be <code>Keyword</code>, and instantiate the polymorphic
type as <code>[Keyword -&gt; Keyword]</code>.</p><h2 id="bounds">Bounds</h2><p>Type variables support upper and lower type bounds, which default to <code>Any</code> and <code>Nothing</code>
respectively.</p><p>Equivalently, the type:</p><pre><code class="clojure">(All [x] ...)
</code></pre><p>is shorthand for:</p><pre><code class="clojure">(All [[x :&gt; Nothing :&lt; Any]] ...)
</code></pre><p>We use bounds to ensure a type variable can only be instantiated to a particular type.</p><p>The type of an identity function that only accepts <code>Number</code>s can be written:</p><pre><code class="clojure">(All [[x :&lt; Number]]
[x -&gt; x])
</code></pre><p>Bounds do not seem as useful in core.typed as languages like Java or Scala.
Often, combinations of ordered function intersections and unions are more useful.</p><p>Bounds are also recursive: a bound can refer to the variable it's bounding.
Type variables to the left of the type variable being bounded in the same binder are in scope in a bound.</p><h2 id="higher-kinded-variables">Higher-kinded variables</h2><p>Note: Experimental feature</p><p>A type variable can be of a higher-kind.</p><pre><code class="clojure">(def-alias AnyMonad
(TFn [[m :kind (TFn [[x :variance :covariant]] Any)]]
'{:m-bind (All [x y]
[(m x) [x -&gt; (m y)] -&gt; (m y)])
:m-result (All [x]
[x -&gt; (m x)])
:m-zero (U (All [x] (m x)) Undefined)
:m-plus (U (All [x]
[(m x) * -&gt; (m x)])
Undefined)}))
</code></pre><p>In this type, <code>x</code> is a type function taking a type and returning a type.
For those familiar with Haskell, <code>x</code> is of kind <code>* -&gt; *</code>.</p><p>The type function is also covariant, which further ensures <code>x</code> is instantiated
to a covariant type function.</p>
<div id="prev-next">
<a href="../start/annotations/index.html">&laquo; core.typed - Annotations</a>
||
<a href="../filters/index.html">core.typed - Filters &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,241 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Quick Guide</title>
<meta name="description" content="Design choicesAll vars must have annotated static types">
<meta property="og:description" content="Design choicesAll vars must have annotated static types">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/quick_guide/" />
<meta property="og:title" content="core.typed - Quick Guide" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/quick_guide/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Quick Guide</h2>
</div>
<h2 id="design-choices">Design choices</h2><h3 id="all-vars-must-have-annotated-static-types">All vars must have annotated static types</h3><p>Use <code>clojure.core.typed/ann</code> to assign types to vars</p><p>eg. Assign <code>my-fn</code> in the current namespace the type <code>[Any -&gt; Any]</code> (a function of one argument).</p><pre><code class="clojure">(ann my-fn [Any -&gt; Any])
</code></pre><h3 id="type-checking-is-separate-to-compilation-and-must-be-explicitly-run">Type checking is separate to compilation and must be explicitly run</h3><p>Use <code>clojure.core.typed/check-ns</code> to type check the current namespace.
This can be done at the REPL.</p><p>Note: Global annotations like <code>ann</code> are only valid when found in a namespace currently being
checked with <code>check-ns</code>, or wrapped in a <code>cf</code>. A raw <code>ann</code> in a REPL has <em>no effect</em>.
Global annotations should be top-level forms or inside a (possibly nested) top-level <code>do</code>.</p><h3 id="all-function-arguments-need-to-be-annotated-or-default-to-any">All function arguments need to be annotated, or default to <code>Any</code></h3><p>Use <code>clojure.core.typed/ann-form</code> to annotate a function.</p><p>eg.</p><pre><code class="clojure">(ann-form #(+ 1 %) [Number -&gt; Number])
</code></pre><h3 id="everything-is-type-checked-but-coretyped-can-ignore-certain-expressions">Everything is type checked, but core.typed can ignore certain expressions</h3><p>core.typed is early in development and there are Clojure idioms it cannot
currently type check. Wrap top-level expressions in <code>clojure.core.typed/tc-ignore</code>
to ignore them.</p><p>Suggestion: If porting a namespace to core.typed, initially use <code>tc-ignore</code> liberally to ignore problematic
code while determining the types for expressions. Once most vars are annotated, revisit
these sites to determine the issue.</p><h2 id="debugging">Debugging</h2><h3 id="print-env-is-your-friend"><code>print-env</code> is your friend</h3><p><code>clojure.core.typed/print-env</code> takes a debug string and prints the local type environment at the current expression.</p><h3 id="use-cf-to-experiment-at-the-repl">Use <code>cf</code> to experiment at the REPL</h3><p><code>clojure.core.typed/cf</code> takes an expression and optionally an expected type and type checks the expression,
returning its inferred type.</p><p>eg.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (fn [a]
{:pre [(number? a)]}
(inc a)))
[(Fn [Any -&gt; java.lang.Number]) {:then tt, :else ff}]
</code></pre><p>If <code>cf</code> returns a vector of results, the first element is the static type.</p><h3 id="use-ann-form-to-ensure-expressions-are-particular-types">Use <code>ann-form</code> to ensure expressions are particular types</h3><p><code>clojure.core.typed/ann-form</code> can be used as a kind of static <code>assert</code>.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (let [a (+ 1 2)
_ (ann-form a clojure.lang.Symbol)]
a))
#&lt;AssertionError java.lang.AssertionError: Assert failed: 6: Local binding a expected type clojure.lang.Symbol, but actual type clojure.core.typed/AnyInteger
(or (not expected) (subtype? t (ret-t expected)))&gt;
</code></pre><h3 id="coretyped-understands-assertions-and-conditionals">core.typed understands assertions and conditionals</h3><p>Normal "untyped" Clojure code often use type predicates combined with assertions or conditionals to direct control flow.
core.typed uses them to gain type information about the current environment.</p><pre><code class="clojure">(let [a (ann-form 1 Number)
_ (print-env "before assert")
_ (assert (integer? a))
_ (print-env "after assert")])
; "before assert"{:env {a java.lang.Number},
; :props ()}
; "after assert"{:env {_28338 nil, _ nil, a clojure.core.typed/AnyInteger},
; :props ((is clojure.core.typed/AnyInteger a) (when (! (U false nil) _) ff) (when (! (U false nil) _) ff) (when (! (U false nil) _28338) ff))}
</code></pre><p>The <code>:env</code> map is maps local bindings to their current types.
<code>:props</code> is a list of propositions currently in scope (can usually be ignored, mostly useful for internal debugging purposes).</p><p>Notice the local binding <code>a</code> has a more accurate type after the <code>assert</code> expression.</p><p>Note: core.typed operates on a hygienic AST, so shadowed bindings will have gensymed names.</p><h2 id="typing-core-constructs">Typing core constructs</h2><h3 id="coretyped-understands-datatype-definitions">core.typed understands datatype definitions</h3><p>Use <code>clojure.core.typed/ann-datatype</code> to give a datatype an expected type.</p><h3 id="use-defprotocol-instead-of-defprotocol">Use <code>defprotocol&gt;</code> instead of <code>defprotocol</code></h3><p>core.typed currently cannot understand protocol definitions. Simply replace references to <code>defprotocol</code>
with <code>clojure.core.typed/defprotocol&gt;</code></p><h3 id="coretyped-understands-simple-multimethods">core.typed understands simple multimethods</h3><p>core.typed can infer accurate types for multimethods that dispatch on simple things like keywords or <code>class</code>.
Just assign an expected type to the multimethod's var with <code>ann</code> and core.typed will use it to infer accurate
types in each <code>defmethod</code>.</p><p>If in doubt whether a multimethod is being inferred properly, use the debugging techniques to double check.
core.typed may not throw an exception if the dispatch is too complex to type check currently.</p><h3 id="macros--macro-definitions">Macros &amp; Macro Definitions</h3><p>Macro definitions are ignored. The type checker operates on the macroexpanded form from
the Compiler's analysis phase.</p><h2 id="type-syntax">Type Syntax</h2><h3 id="types-use-the-current-global-scope-of-the-namespace">Types use the current global scope of the namespace</h3><p>Simply adding an <code>(:import ...)</code> to the <code>ns</code> declaration as usual in Clojure brings the class name into scope.
Otherwise, refers to classes via their fully qualified name.</p>
<div id="prev-next">
<a href="rationale/index.html">&laquo; core.typed - Rationale</a>
||
<a href="start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="rationale/index.html">core.typed - Rationale</a></li>
<li><a href="quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="types/index.html">core.typed - Types</a></li>
<li><a href="start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="filters/index.html">core.typed - Filters</a></li>
<li><a href="mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="function_types/index.html">core.typed - Functions</a></li>
<li><a href="limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,241 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Quick Guide</title>
<meta name="description" content="Design choicesAll vars must have annotated static types">
<meta property="og:description" content="Design choicesAll vars must have annotated static types">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/quick_guide/" />
<meta property="og:title" content="core.typed - Quick Guide" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/quick_guide/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Quick Guide</h2>
</div>
<h2 id="design-choices">Design choices</h2><h3 id="all-vars-must-have-annotated-static-types">All vars must have annotated static types</h3><p>Use <code>clojure.core.typed/ann</code> to assign types to vars</p><p>eg. Assign <code>my-fn</code> in the current namespace the type <code>[Any -&gt; Any]</code> (a function of one argument).</p><pre><code class="clojure">(ann my-fn [Any -&gt; Any])
</code></pre><h3 id="type-checking-is-separate-to-compilation-and-must-be-explicitly-run">Type checking is separate to compilation and must be explicitly run</h3><p>Use <code>clojure.core.typed/check-ns</code> to type check the current namespace.
This can be done at the REPL.</p><p>Note: Global annotations like <code>ann</code> are only valid when found in a namespace currently being
checked with <code>check-ns</code>, or wrapped in a <code>cf</code>. A raw <code>ann</code> in a REPL has <em>no effect</em>.
Global annotations should be top-level forms or inside a (possibly nested) top-level <code>do</code>.</p><h3 id="all-function-arguments-need-to-be-annotated-or-default-to-any">All function arguments need to be annotated, or default to <code>Any</code></h3><p>Use <code>clojure.core.typed/ann-form</code> to annotate a function.</p><p>eg.</p><pre><code class="clojure">(ann-form #(+ 1 %) [Number -&gt; Number])
</code></pre><h3 id="everything-is-type-checked-but-coretyped-can-ignore-certain-expressions">Everything is type checked, but core.typed can ignore certain expressions</h3><p>core.typed is early in development and there are Clojure idioms it cannot
currently type check. Wrap top-level expressions in <code>clojure.core.typed/tc-ignore</code>
to ignore them.</p><p>Suggestion: If porting a namespace to core.typed, initially use <code>tc-ignore</code> liberally to ignore problematic
code while determining the types for expressions. Once most vars are annotated, revisit
these sites to determine the issue.</p><h2 id="debugging">Debugging</h2><h3 id="print-env-is-your-friend"><code>print-env</code> is your friend</h3><p><code>clojure.core.typed/print-env</code> takes a debug string and prints the local type environment at the current expression.</p><h3 id="use-cf-to-experiment-at-the-repl">Use <code>cf</code> to experiment at the REPL</h3><p><code>clojure.core.typed/cf</code> takes an expression and optionally an expected type and type checks the expression,
returning its inferred type.</p><p>eg.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (fn [a]
{:pre [(number? a)]}
(inc a)))
[(Fn [Any -&gt; java.lang.Number]) {:then tt, :else ff}]
</code></pre><p>If <code>cf</code> returns a vector of results, the first element is the static type.</p><h3 id="use-ann-form-to-ensure-expressions-are-particular-types">Use <code>ann-form</code> to ensure expressions are particular types</h3><p><code>clojure.core.typed/ann-form</code> can be used as a kind of static <code>assert</code>.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (let [a (+ 1 2)
_ (ann-form a clojure.lang.Symbol)]
a))
#&lt;AssertionError java.lang.AssertionError: Assert failed: 6: Local binding a expected type clojure.lang.Symbol, but actual type clojure.core.typed/AnyInteger
(or (not expected) (subtype? t (ret-t expected)))&gt;
</code></pre><h3 id="coretyped-understands-assertions-and-conditionals">core.typed understands assertions and conditionals</h3><p>Normal "untyped" Clojure code often use type predicates combined with assertions or conditionals to direct control flow.
core.typed uses them to gain type information about the current environment.</p><pre><code class="clojure">(let [a (ann-form 1 Number)
_ (print-env "before assert")
_ (assert (integer? a))
_ (print-env "after assert")])
; "before assert"{:env {a java.lang.Number},
; :props ()}
; "after assert"{:env {_28338 nil, _ nil, a clojure.core.typed/AnyInteger},
; :props ((is clojure.core.typed/AnyInteger a) (when (! (U false nil) _) ff) (when (! (U false nil) _) ff) (when (! (U false nil) _28338) ff))}
</code></pre><p>The <code>:env</code> map is maps local bindings to their current types.
<code>:props</code> is a list of propositions currently in scope (can usually be ignored, mostly useful for internal debugging purposes).</p><p>Notice the local binding <code>a</code> has a more accurate type after the <code>assert</code> expression.</p><p>Note: core.typed operates on a hygienic AST, so shadowed bindings will have gensymed names.</p><h2 id="typing-core-constructs">Typing core constructs</h2><h3 id="coretyped-understands-datatype-definitions">core.typed understands datatype definitions</h3><p>Use <code>clojure.core.typed/ann-datatype</code> to give a datatype an expected type.</p><h3 id="use-defprotocol-instead-of-defprotocol">Use <code>defprotocol&gt;</code> instead of <code>defprotocol</code></h3><p>core.typed currently cannot understand protocol definitions. Simply replace references to <code>defprotocol</code>
with <code>clojure.core.typed/defprotocol&gt;</code></p><h3 id="coretyped-understands-simple-multimethods">core.typed understands simple multimethods</h3><p>core.typed can infer accurate types for multimethods that dispatch on simple things like keywords or <code>class</code>.
Just assign an expected type to the multimethod's var with <code>ann</code> and core.typed will use it to infer accurate
types in each <code>defmethod</code>.</p><p>If in doubt whether a multimethod is being inferred properly, use the debugging techniques to double check.
core.typed may not throw an exception if the dispatch is too complex to type check currently.</p><h3 id="macros--macro-definitions">Macros &amp; Macro Definitions</h3><p>Macro definitions are ignored. The type checker operates on the macroexpanded form from
the Compiler's analysis phase.</p><h2 id="type-syntax">Type Syntax</h2><h3 id="types-use-the-current-global-scope-of-the-namespace">Types use the current global scope of the namespace</h3><p>Simply adding an <code>(:import ...)</code> to the <code>ns</code> declaration as usual in Clojure brings the class name into scope.
Otherwise, refers to classes via their fully qualified name.</p>
<div id="prev-next">
<a href="../rationale/index.html">&laquo; core.typed - Rationale</a>
||
<a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,227 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Rationale</title>
<meta name="description" content="Static typing has well known benefits. For example, statically typed languages catch many common
programming errors at the earliest time possible: compile time.
Types also serve as an excellent form of (machine checkable) documentation that
almost always augment existing hand-written documentation.Languages without static type checking (dynamically typed) bring other benefits.
Without the strict rigidity of mandatory static typing, they can provide more flexible and forgiving
idioms that can help in rapid prototyping.
Often the benefits of static type checking are desired as the program grows.">
<meta property="og:description" content="Static typing has well known benefits. For example, statically typed languages catch many common
programming errors at the earliest time possible: compile time.
Types also serve as an excellent form of (machine checkable) documentation that
almost always augment existing hand-written documentation.Languages without static type checking (dynamically typed) bring other benefits.
Without the strict rigidity of mandatory static typing, they can provide more flexible and forgiving
idioms that can help in rapid prototyping.
Often the benefits of static type checking are desired as the program grows.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/rationale/" />
<meta property="og:title" content="core.typed - Rationale" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/rationale/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Rationale</h2>
</div>
<p>Static typing has well known benefits. For example, statically typed languages catch many common
programming errors at the earliest time possible: compile time.
Types also serve as an excellent form of (machine checkable) documentation that
almost always augment existing hand-written documentation.</p><p>Languages without static type checking (dynamically typed) bring other benefits.
Without the strict rigidity of mandatory static typing, they can provide more flexible and forgiving
idioms that can help in rapid prototyping.
Often the benefits of static type checking are desired as the program grows.</p><p>This work adds static type checking (and some of its benefits) to Clojure, a dynamically typed language,
while still preserving idioms that characterise the language.
It allows static and dynamically typed code to be mixed so the programmer can use whichever
is more appropriate.</p><p>(For a detailed treatment, see my Honours Dissertation, <a href="https://github.com/downloads/frenchy64/papers/ambrose-honours.pdf">A Practical Optional Type System for Clojure</a>)</p>
<div id="prev-next">
<a href="../user_documentation/index.html">&laquo; core.typed - User Documentation</a>
||
<a href="../quick_guide.html">core.typed - Quick Guide &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,275 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Annotations</title>
<meta name="description" content="core.typed requires a moderate amount of assistance from the user to help infer types.There are two main things that need annotating:">
<meta property="og:description" content="core.typed requires a moderate amount of assistance from the user to help infer types.There are two main things that need annotating:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/start/annotations/" />
<meta property="og:title" content="core.typed - Annotations" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/start/annotations/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Annotations</h2>
</div>
<p>core.typed requires a moderate amount of assistance from the user to help infer types.</p><p>There are two main things that need annotating:</p><ol><li>All vars must be annotated</li><li>All function parameters must be annotated, or default to <code>Any</code>.</li></ol><p>From the provided annotations, core.typed uses local type inference to infer
the types for local bindings, interop calls, and other expressions, mostly
without further assistance.</p><h2 id="vars">Vars</h2><p>When core.typed finds a var reference, <code>def</code>, <code>binding</code>, or some other var-related construct
that relys on the derefereced value of a var, it requires an expected type.</p><pre><code class="clojure">clojure.core.typed=&gt; (declare abc)
#'clojure.core.typed/abc
clojure.core.typed=&gt; (cf abc)
#&lt;AssertionError java.lang.AssertionError: Assert failed: Untyped var reference: clojure.core.typed/abc
(contains? (clojure.core/deref *var-annotations*) nsym)&gt;
</code></pre><h3 id="vars-in-current-namespace">Vars in current namespace</h3><p>Use <code>clojure.core.typed/ann</code> to associate a static type with a var.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (ann abc Number))
[clojure.core.typed/abc java.lang.Number]
clojure.core.typed=&gt; (cf (def abc 1))
clojure.lang.Var
clojure.core.typed=&gt; (cf abc)
java.lang.Number
</code></pre><p><code>ann</code> qualifies the var in the current namespace if unqualified.</p><h3 id="vars-in-other-namespaces">Vars in other namespaces</h3><p>Sometimes vars from other namespaces need annotation. Just qualify the var as you
would in the current namespace (aliases are recognised) to associate it with a static type.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf clojure.core/*compile-path*)
#&lt;AssertionError java.lang.AssertionError: Assert failed: Untyped var reference: clojure.core/*compile-path*
(contains? (clojure.core/deref *var-annotations*) nsym)&gt;
clojure.core.typed=&gt; (cf (ann clojure.core/*compile-path* String))
[clojure.core/*compile-path* java.lang.String]
clojure.core.typed=&gt; (cf clojure.core/*compile-path*)
java.lang.String
</code></pre><h3 id="unchecked-vars">Unchecked Vars</h3><p>We can instruct core.typed to ignore certain var definitions by adding <code>:nocheck</code> metadata
to <code>ann</code> forms.</p><pre><code class="clojure">(ns typed.nocheck
(:require [clojure.core.typed :refer [ann-nocheck ann check-ns]]))
(ann ^:nocheck foo [Number -&gt; Number])
(defn foo [a]
'a)
(ann bar [Number -&gt; Number])
(defn bar [b]
(+ 2 (foo b)))
</code></pre><h3 id="var-warnings">Var Warnings</h3><p>After type checking has been performed, core.typed warns about vars that have been assigned types
but have no corresponding checked <code>def</code> form. The <code>def</code> must at least make a binding,
so it would be a warning if the var was only <code>declare</code>d.</p><pre><code class="clojure">(ns clojure.core.typed.test.nocheck
(:require [clojure.core.typed :refer [ann-nocheck ann check-ns]]))
(ann ^:nocheck foo [Number -&gt; Number])
(defn foo [a]
'a)
(ann bar [Number -&gt; Number])
(defn bar [b]
(+ 2 (foo b)))
;(check-ns)
; ...
; WARNING: Var clojure.core.typed.test.var-usage/foo used without checking definition
;=&gt; nil
</code></pre><h2 id="functions">Functions</h2><p>There are several ways to annotate a function type.</p><h3 id="partial-annotation-with-fn">Partial annotation with <code>fn&gt;</code></h3><p>To annotate just the arguments of a <code>fn</code>, use the <code>fn&gt;</code> wrapper. It is exactly like <code>fn</code>,
except each argument is wrapped in a vector which includes its static type.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (fn&gt; [[a :- Number]] (+ a 1)))
[(Fn [java.lang.Number -&gt; java.lang.Number]) {:then tt, :else ff}]
</code></pre><p>All the usual destructuring is supported.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (fn&gt; [[{:keys [a b c]} :- '{:a Number :b Long :c Double}]]
[a b c]))
[(Fn ['{:a java.lang.Number, :b java.lang.Long, :c java.lang.Double} -&gt; '[java.lang.Number java.lang.Long java.lang.Double]])
{:then tt, :else ff}]
</code></pre><h3 id="full-annotation-with-ann-form">Full annotation with <code>ann-form</code></h3><p>Often it is more useful to provide a full function type as a <code>fn</code>'s annotation. This
especially works well with Clojure's anonymous function syntax.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (ann-form #(inc %)
[Number -&gt; Number]))
(Fn [java.lang.Number -&gt; java.lang.Number])
</code></pre><p>This way, you can also assign anonymous functions ordered intersection function types.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (fn [a]
(cond
(number? a) 1
(symbol? a) 'a))
(Fn [Number -&gt; Number]
[Symbol -&gt; Symbol]))
(Fn [java.lang.Number -&gt; java.lang.Number]
[clojure.lang.Symbol -&gt; clojure.lang.Symbol])
</code></pre>
<div id="prev-next">
<a href="../../types/index.html">&laquo; core.typed - Types</a>
||
<a href="../../poly_fn/index.html">core.typed - Polymorphic Functions &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../../about/index.html">About</a></li>
<li><a href="../../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../../community/index.html">Clojure Community</a></li>
<li><a href="../../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../types/index.html">core.typed - Types</a></li>
<li><a href="index.html">core.typed - Annotations</a></li>
<li><a href="../../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../filters/index.html">core.typed - Filters</a></li>
<li><a href="../../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,237 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Getting Started: Introduction and Motivation</title>
<meta name="description" content="core.typed is an optional type system for Clojure. If you are interesting in how core.typed
can help you verify your programs as correct, read on.&quot;I use Clojure to avoid types!&quot;">
<meta property="og:description" content="core.typed is an optional type system for Clojure. If you are interesting in how core.typed
can help you verify your programs as correct, read on.&quot;I use Clojure to avoid types!&quot;">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/start/introduction_and_motivation/" />
<meta property="og:title" content="core.typed - Getting Started: Introduction and Motivation" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/start/introduction_and_motivation/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Getting Started: Introduction and Motivation</h2>
</div>
<p>core.typed is an optional type system for Clojure. If you are interesting in how core.typed
can help you verify your programs as correct, read on.</p><h2 id="i-use-clojure-to-avoid-types">"I use Clojure to avoid types!"</h2><p>Many programmers use Clojure as relief from popular typed languages such as Java or C#.
Java's verbosity and redundant type annotations help make the move to Clojure feel liberating
and enjoyable: so why go back to types?</p><p>core.typed has a different story to tell:</p><ul><li>type checking is optional
<ul><li>only use the type system where you need it</li></ul></li><li>local type inference is used to infer local bindings
<ul><li>locals rarely need type annotations</li></ul></li><li>it can type check (mostly) normal Clojure code
<ul><li>the Clojure you know and love!</li></ul></li></ul><p>If Java has driven you away from types, core.typed could be pleasant surprise.
It might even become one of your go-to tools for code verification in Clojure.</p><h2 id="what-are-types">What are types?</h2><p>This is a good question, especially in the context of a dynamically-typed (DT) language
where we don't have "types".</p><p>We use the term "type" to mean static type and "tag" for runtime tags.
Types only exist at compile time and are used by the static type system to model runtime
invariants and properties.</p><p>Thinking of compile-time and runtime as distinct phases in terms of types often helps.
The type system uses types to reason about the runtime behaviour of code, which can
also include tag invariants.</p><p>There are no types in Clojure, only tags. We can also say that Clojure has exactly one type: <code>Any</code> (subtype of all types).
The closest equivalent to types we have
are ad-hoc comments or doc-strings which describe the input/output behaviour
of functions.</p><p>For example, the <code>number?</code> predicate returns true if its (runtime) argument
has a tag that is a subtype of <code>java.lang.Number</code>, otherwise false. In core.typed
we use a type to model these invariants.
The tag of <code>number?</code> might be <code>IFn</code>, while its type is <code>[Any -&gt; boolean :filters {:then (is Number 0) :else (! Number 0)}]</code>.</p><p>In summary:</p><ul><li>types only exist at compile time</li><li>tags only exist at runtime</li></ul><h2 id="why-types">Why types?</h2><p>Why use types at all? A static type checker gives earlier and often clearer type errors.</p><p>For example, you might observe:</p><ul><li>fewer "Boolean is not an ISeq" errors without line numbers in production</li><li>more "Cannot pass Boolean to second argument of map" with line numbers at compile time in development.</li></ul><p>Types, when coupled with an appropriate doc-string, are excellent machine checkable documentation.
They never go out of date, and are often invaluable as a quick reminder of what a function does.</p><p>Types are useful when a program grows, especially when there are multiple contributors.
If a contribution passes the type system, we know that it is type correct (type errors are amongst
the most common user errors in programming).</p><h2 id="great-types-are-the-answer">Great, types are the answer!</h2><p>Not quite. Types can help verify that a program is basically correct, but not if it does the right thing.
Use as many verification techniques as you can: core.typed works great coupled with unit testing or
generative testing.</p><p>Clojure simply is not built with static typing in mind. It is impractical to expect core.typed alone
to prevent as many user errors as say Haskell's type system: core.typed either needs to choose some
subset of Clojure optimised for user error prevention, or attempt to check all Clojure code
while making some compromises (it does the latter).</p><p>This might seem discouraging, but in practice core.typed will catch all type errors in your code.
The problem is some Clojure idioms are so flexible it is often impossible to distinguish
between intended and unintended usage.</p><p>A small example: <code>map</code> accepts either <code>nil</code> or a <code>Seqable</code> as a second argument. It is perfectly
valid to provide an argument that is always <code>nil</code>, but it's probably not what the user intended.</p><p>So for best results, couple core.typed with all the usual testing/verification techniques.</p><h2 id="before-we-begin">Before we begin</h2><p>There are some details to keep in mind when using core.typed before you jump in to use it.</p><p>Read the <a href="../../quick_guide.html">Quick Guide</a>, and keep a copy handy when you follow along the rest of the tutorial.</p>
<div id="prev-next">
<a href="../../quick_guide.html">&laquo; core.typed - Quick Guide</a>
||
<a href="../../types/index.html">core.typed - Types &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../../about/index.html">About</a></li>
<li><a href="../../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../../community/index.html">Clojure Community</a></li>
<li><a href="../../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../types/index.html">core.typed - Types</a></li>
<li><a href="../annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../filters/index.html">core.typed - Filters</a></li>
<li><a href="../../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,338 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - Types</title>
<meta name="description" content="Common typesAny and Nothing">
<meta property="og:description" content="Common typesAny and Nothing">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/types/" />
<meta property="og:title" content="core.typed - Types" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/types/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - Types</h2>
</div>
<h2 id="common-types">Common types</h2><h3 id="any-and-nothing">Any and Nothing</h3><p>Every type is a subtype to <code>Any</code>, written <code>x &lt;: Any</code> for all types <code>x</code>. Equivalently, any place that <code>Any</code> is valid,
any other type can be used. <code>Any</code> is also known as the "Top" type.</p><p>Conversely, there are no types that are subtypes to <code>Nothing</code>. However for all types <code>x</code>
it holds that <code>Nothing &lt;: x</code>. Put another way, <code>Nothing</code> is a valid type to give use
in positions expecting any other type. In practice, <code>Nothing</code> is not as useful as <code>Any</code>,
and is usually used internally to detect dead code and other code properties.</p><h3 id="functions">Functions</h3><p>core.typed has a special function type, which is an <em>ordered intersection</em> of arities.
It allows us to specify fine grained function invariants.</p><p>Starting simply,</p><pre><code class="clojure">(Fn [Any -&gt; Any])
</code></pre><p>is a function taking one argument of type <code>Any</code>. <code>[Any -&gt; Any]</code>
is an equivalent shorthand for single-arity function types.</p><h4 id="multiple-arities">Multiple arities</h4><p>We can specify multiple arities:</p><pre><code class="clojure">(Fn [Any -&gt; Any]
[Any Any -&gt; Any])
</code></pre><p>Here we can call a function of this type with either one or two arguments.
In this case, the ordered intersection type acts as a simple overloading on arity.</p><p>Finer invariants can be expressed by specifying multiple signatures of the same arity:</p><pre><code class="clojure">(Fn [Symbol -&gt; Number]
[Number -&gt; Symbol])
</code></pre><p>This function returns a <code>Number</code> if passed a <code>Symbol</code>, and returns a <code>Symbol</code> if passed a <code>Number</code>.</p><p>The exact return type for a function application expression involving multiple arities
is chosen by matching the actual types provided with each arities, top-to-bottom
(this explains why our functions are "ordered" intersections).
In this case, each arity is disjoint because no combination of arguments could
potentially trigger both arities. More concretely, there is no type that is both
a <code>Symbol</code> and a <code>Number</code>, so at most one arity triggers for any given arguments.</p><p>Overlapping arities hints at the power of ordered intersections.</p><pre><code class="clojure">(Fn [Long -&gt; Symbol]
[Number -&gt; Keyword])
</code></pre><p>This type always returns a <code>Symbol</code> for <code>Long</code> arguments.</p><p>Beware, swapping the arities produces different results!</p><pre><code class="clojure">(Fn [Number -&gt; Keyword]
[Long -&gt; Symbol])
</code></pre><p>The first arity always "wins" because <code>Number</code> is strictly more general than <code>Long</code>.
Arities are usually ordered from more-specific parameters to less-specific parameters.</p><p>What about arities that have partially overlapping parameters?
Consider:</p><pre><code class="clojure">(Fn [Long Any -&gt; Keyword]
[Any Number -&gt; Symbol])
</code></pre><p>Calling with <code>Long</code> <code>Long</code> arguments gives <code>Keyword</code>, and <code>Number</code> <code>Long</code> gives <code>Symbol</code>.</p><p>Flipping the arities gives different results:</p><pre><code class="clojure">(Fn [Any Number -&gt; Symbol]
[Long Any -&gt; Keyword])
</code></pre><p>Now <code>Long</code> <code>Long</code> gives <code>Symbol</code>, and <code>Number</code> <code>Long</code> gives <code>Symbol</code>.
Partially overlapping arities can be tricky and can unexpectedly trigger earlier arities,
so care must be taken here.</p><p>Finally, a common idiom is to provide a base arity, which has arguments at least as general
as the ones above it.</p><p>For example, we might want our function of type <code>(Fn [Long -&gt; Symbol] [Number -&gt; Keyword])</code> to handle the case where
the argument is <em>either</em> a <code>Long</code> or a <code>Number</code>.
We can express this by using a union (to express a least-upper-bound of <code>Long</code> and <code>Number</code>).</p><pre><code class="clojure">(Fn [Long -&gt; Symbol]
[Number -&gt; Keyword]
[(U Long Number) -&gt; (U Symbol Keyword)])
</code></pre><p>Note the result type is sufficiently general to show the result type is either a <code>Symbol</code> or <code>Keyword</code>.</p><h4 id="rest-parameters">Rest parameters</h4><p>Rest parameters are specified using a <code>*</code>.</p><p>eg.</p><pre><code class="clojure">(Fn [Any Number * -&gt; Any])
</code></pre><p>is a function taking at least one parameter, and any number of parameters after it
of type <code>Number</code>.</p><h4 id="keyword-parameters">Keyword parameters</h4><p>Keyword parameters are specified using <code>&amp;</code> after the fixed domain.</p><p>eg.</p><pre><code class="clojure">(Fn [Any &amp; {:a Number} -&gt; Any])
</code></pre><p>is a function that takes a fixed parameter and an optional keyword argument <code>:a</code>, of
type <code>Number</code>.</p><p>We can also specify mandatory keyword parameters:</p><pre><code class="clojure">(Fn [Any &amp; {} :mandatory {:a Number} -&gt; Any])
</code></pre><p>is the same function, except the keyword argumetn <code>:a</code> now must be present when calling.</p><p>We can express finer grained invariants by combining keyword types and ordered
function intersection types:</p><pre><code class="clojure">(Fn [Any &amp; {} :mandatory {:a Number :b Number} -&gt; Number]
[Any &amp; {:a Number :b Number} -&gt; Any])
</code></pre><p>This function type returns a <code>Number</code> if provided both <code>:a</code> and <code>:b</code> parameters,
otherwise returns <code>Any</code> if some other combination of <code>:a</code> and <code>:b</code> is provided.</p><h3 id="java-classes">Java Classes</h3><p>core.typed reuses Java and clojure.lang.* classes. The normal scoping rules apply in types,
e.g., use <code>:import</code> to bring classes into scope.</p><p>Note: <code>java.lang.*</code> classes are implicitly in scope in Clojure namespaces.</p><h3 id="numbers-strings-and-other-java-types">Numbers, Strings and other Java types</h3><p>core.typed follows the normal rules that apply to Clojure code.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf 1 Long)
java.lang.Long
clojure.core.typed=&gt; (cf 1.1 Double)
java.lang.Double
clojure.core.typed=&gt; (cf "a" String)
java.lang.String
clojure.core.typed=&gt; (cf \a Character)
java.lang.Character
</code></pre><h3 id="symbols-and-keywords">Symbols and Keywords</h3><p>Symbols and Keywords are instances of their corresponding clojure.lang classes.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf 'a clojure.lang.Symbol)
clojure.lang.Symbol
clojure.core.typed=&gt; (cf :a clojure.lang.Keyword)
clojure.lang.Keyword
</code></pre><h3 id="seqables">Seqables</h3><p>Seqables extend <code>(Seqable a)</code>, which is covariant in its argument.
Types that extend <code>(Seqable a</code>) are capable of creating a sequence
(aka. an <code>(ISeq a)</code>) representation of itself via functions like <code>seq</code>.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf {'a 2 'b 3} (Seqable (IMapEntry Symbol Number)))
(clojure.lang.Seqable (clojure.lang.IMapEntry clojure.lang.Symbol java.lang.Number))
clojure.core.typed=&gt; (cf [1 2 3] (Seqable Number))
(clojure.lang.Seqable java.lang.Number)
clojure.core.typed=&gt; (cf '#{a b c} (Seqable Symbol))
(clojure.lang.Seqable clojure.lang.Symbol)
</code></pre><h3 id="seqs">Seqs</h3><p>Seqs extend <code>(ISeq a)</code>, which is covariant in its argument.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (seq [1 2]) (ISeq Number))
(clojure.lang.ISeq java.lang.Number)
</code></pre><h3 id="lists">Lists</h3><p>Lists extend <code>(IPersistentList a)</code>, which is covariant in its argument.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf '(1 2) (IPersistentList Number))
(clojure.lang.IPersistentList java.lang.Number)
</code></pre><h3 id="vectors">Vectors</h3><p>Vectors extend <code>(IPersistentVector a)</code>, which is covariant in its argument.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf [1 2] (IPersistentVector Number))
(clojure.lang.IPersistentVector java.lang.Number)
</code></pre><h3 id="maps">Maps</h3><p>Maps extend <code>(IPersistentMap a b)</code>, which is covariant in both its arguments.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf {'a 1 'b 3} (IPersistentMap Symbol Long))
(clojure.lang.IPersistentMap clojure.lang.Symbol java.lang.Long)
</code></pre><h3 id="sets">Sets</h3><p>Sets extend <code>(IPersistentSet a)</code>, which is covariant in its argument.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf #{1 2 3} (IPersistentSet Number))
(clojure.lang.IPersistentSet java.lang.Number)
</code></pre><h3 id="atoms">Atoms</h3><p>An Atom of type <code>(Atom w r)</code> can accept values of type <code>w</code> and provide values of type <code>r</code>.
It is contravariant in <code>w</code> and covariant in <code>r</code>.</p><p>Usually <code>w</code> and <code>r</code> are identical, so an alias <code>(clojure.core.typed/Atom1 wr)</code> is provided,
which is equivalent to <code>(Atom wr wr)</code>.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (atom {}) (Atom1 (IPersistentMap Symbol Number)))
(clojure.core.typed/Atom1 (clojure.lang.IPersistentMap clojure.lang.Symbol java.lang.Number))
</code></pre><h2 id="type-grammar">Type Grammar</h2><p>A rough grammar for core.typed types.</p><pre><code>Type := nil
| true
| false
| (U Type*)
| (I Type+)
| FunctionIntersection
| (Value CONSTANT-VALUE)
| (Rec [Symbol] Type)
| (All [Symbol+] Type)
| (All [Symbol* Symbol ...] Type)
| (HMap {Keyword Type*}) ;eg (HMap {:a (Value 1), :b nil})
| '{Keyword Type*} ;eg '{:a (Value 1), :b nil}
| (Vector* Type*)
| '[Type*]
| (Seq* Type*)
| (List* Type*)
| Symbol ;class/protocol/free resolvable in context
FunctionIntersection := ArityType
| (Fn ArityType+)
ArityType := [FixedArgs -&gt; Type]
| [FixedArgs RestArgs * -&gt; Type]
| [FixedArgs DottedType ... Symbol -&gt; Type]
FixedArgs := Type*
RestArgs := Type
DottedType := Type
</code></pre><h2 id="types">Types</h2><h3 id="value-shorthands">Value shorthands</h3><p><code>nil</code>, <code>true</code> and <code>false</code> resolve to the respective singleton types for those values</p><h3 id="intersections">Intersections</h3><p><code>(I Type+)</code> creates an intersection of types.</p><h3 id="unions">Unions</h3><p><code>(U Type*)</code> creates a union of types.</p><h3 id="functions-1">Functions</h3><p>A function type is an ordered intersection of arity types.</p><p>There is a vector sugar for functions of one arity.</p><h3 id="heterogeneous-maps">Heterogeneous Maps</h3><p><em>Warning</em>: Heterogeneous maps are alpha and their design is subject to change.</p><p>A heterogeneous map type represents a map that has at least a particular set of keyword keys.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf {:a 1})
[(HMap {:a (Value 1)}) {:then tt, :else ff}]
</code></pre><p>This type can also be written <code>'{:a (Value 1)}</code>.</p><p>Lookups of known keys infer accurate types.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (-&gt; {:a 1} :a))
(Value 1)
</code></pre><p>Currently, they are limited (but still quite useful):</p><ul><li>the presence of keys is recorded, but not their absence</li><li>only keyword value keys are allowed.</li></ul><p>These rules have several implications.</p><h4 id="absent-keys">Absent keys</h4><p>Looking up keys that are not recorded as present give inaccurate types</p><pre><code class="clojure">clojure.core.typed=&gt; (cf (-&gt; {:a 1} :b))
Any
</code></pre><h4 id="non-keyword-keys">Non-keyword keys</h4><p>Literal maps without keyword keys are inferred as <code>APersistentMap</code>.</p><pre><code class="clojure">clojure.core.typed=&gt; (cf {(inc 1) 1})
[(clojure.lang.APersistentMap clojure.core.typed/AnyInteger (Value 1)) {:then tt, :else ff}]
</code></pre><p>Optional keys can be defined either by constructing a union of map types, or by passing
the <code>HMap</code> type constructor an <code>:optional</code> keyword argument with a map of optional keys.</p><h3 id="heterogeneous-vectors">Heterogeneous Vectors</h3><p><code>(Vector* (Value 1) (Value 2))</code> is a IPersistentVector of length 2, essentially
representing the value <code>[1 2]</code>. The type <code>'[(Value 1) (Value 2)]</code> is identical.</p><h3 id="polymorphism">Polymorphism</h3><p>The binding form <code>All</code> introduces a number of free variables inside a scope.</p><p>Optionally scopes a dotted variable by adding <code>...</code> after the last symbol in the binder.</p><p>eg. The identity function: <code>(All [x] [x -&gt; x])</code>
eg. Introducing dotted variables: `(All [x y ...] [x y ... y -&gt; x])</p><h3 id="recursive-types">Recursive Types</h3><p><code>Rec</code> introduces a recursive type. It takes a vector of one symbol and a type.
The symbol is scoped to represent the entire type in the type argument.</p><pre><code class="clojure">; Type for {:op :if
; :test {:op :var, :var #'A}
; :then {:op :nil}
; :else {:op :false}}
(Rec [x]
(U (HMap {:op (Value :if)
:test x
:then x
:else x})
(HMap {:op (Value :var)
:var clojure.lang.Var})
(HMap {:op (Value :nil)})
(HMap {:op (Value :false)})))))
</code></pre>
<div id="prev-next">
<a href="../start/introduction_and_motivation/index.html">&laquo; core.typed - Getting Started: Introduction and Motivation</a>
||
<a href="../start/annotations/index.html">core.typed - Annotations &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,257 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: core.typed - User Documentation</title>
<meta name="description" content="UsageType Aliases">
<meta property="og:description" content="UsageType Aliases">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/core_typed/user_documentation/" />
<meta property="og:title" content="core.typed - User Documentation" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/core_typed/user_documentation/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>core.typed - User Documentation</h2>
</div>
<h1 id="usage">Usage</h1><h2 id="type-aliases">Type Aliases</h2><p><code>clojure.core.typed/def-alias</code> defines a type alias.</p><pre><code class="clojure">(def-alias Term (I IUnifyTerms
IUnifyWithNil
IUnifyWithObject
IUnifyWithLVar
IUnifyWithSequential
IUnifyWithMap
IUnifyWithSet
IReifyTerm
IWalkTerm
IOccursCheckTerm
IBuildTerm))
</code></pre><h2 id="primitive-java-arrays">Primitive Java Arrays</h2><p>"Typed" arrays can be created with <code>into-array&gt;</code>, which has a 2 and 3 arity version.</p><p>The correspondence between core.typed types and Java types is subtle here. Usually
<code>into-array&gt;</code> accepts a core.typed type as its first argument, followed by a collection (as <code>clojure.core/into-array</code>).</p><pre><code class="clojure">;; `int` is the primitive int in Java. This creates a primitive array.
(class (into-array&gt; int [1]))
;=&gt; [I
;; This is a Number array with nullable elements.
(class (into-array&gt; (U nil Number) [1]))
;=&gt; [Ljava.lang.Number;
;; This is a Number array with non-nullable elements.
;; Notice this generates the same type as before as Java does not distinguish
;; non-/nullable arrays. core.typed statically disallows nil to be added
;; as an element from any Clojure it checks.
(class (into-array&gt; Number [1]))
;=&gt; [Ljava.lang.Number;
;; An array of nullable primitive ints does not make sense in Java,
;; so it is generalised to an array of Objects.
(class (into-array&gt; (U nil int) [1]))
;=&gt; [Ljava.lang.Object;
;; Unions are often generalised to Object
(class (into-array&gt; (U clojure.lang.Symbol Number) [1]))
;=&gt; [Ljava.lang.Object;
</code></pre><p>When more control is needed of the Java type, the 3 arity version of <code>into-array&gt;</code> accepts
the Java type (in core.typed syntax) as first argument, followed by the Clojure type, and the collection.</p><pre><code class="clojure">;; Generalising to Number instead of Object.
(class (into-array&gt; Number (U Integer Number) [1]))
;=&gt; [Ljava.lang.Number;
</code></pre><p>The Clojure element type should be a subtype to the Java element type.</p><h2 id="declarations">Declarations</h2><p><code>clojure.core.typed/declare-types</code>, <code>clojure.core.typed/declare-names</code> and <code>clojure.core.typed/declare-protocols</code> are similar
to <code>declare</code> in that they allow you to use types before they are defined.</p><pre><code class="clojure">(declare-datatypes Substitutions)
(declare-protocols LVar)
(declare-names MyAlias)
</code></pre><h2 id="checking-typed-namespaces">Checking typed namespaces</h2><p><code>clojure.core.typed/check-ns</code> checks the namespace that its symbol argument represents.</p><pre><code class="clojure">(check-ns 'my.ns)
</code></pre><h2 id="debugging">Debugging</h2><p><code>clojure.core.typed/print-env</code> prints the current environment.</p><pre><code class="clojure">(let [a 1]
(print-env "Env:")
a)
; Prints: "Env:" {:env {a (Value 1)}, ....}
</code></pre><p><code>clojure.core.typed/cf</code> (pronounced "check form") can be used at the REPL to return the type of a form.</p><pre><code class="clojure">(cf 1)
;=&gt; [(Value 1) {:then [top-filter], :else [bot-filter]} empty-object]
</code></pre><h2 id="macros--macro-definitions">Macros &amp; Macro Definitions</h2><p>Macro definitions are ignored. The type checker operates on the macroexpanded form from
the Compiler's analysis phase.</p>
<div id="prev-next">
<a href="../home/index.html">&laquo; core.typed - User Documentation Home</a>
||
<a href="../rationale/index.html">core.typed - Rationale &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="index.html">core.typed - User Documentation</a></li>
<li><a href="../rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../types/index.html">core.typed - Types</a></li>
<li><a href="../start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../filters/index.html">core.typed - Filters</a></li>
<li><a href="../mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../function_types/index.html">core.typed - Functions</a></li>
<li><a href="../limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,208 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Data Processing (Help Wanted)</title>
<meta name="description" content="Help wantedPlease follow the instructions on how to contribute and start writing over here">
<meta property="og:description" content="Help wantedPlease follow the instructions on how to contribute and start writing over here">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/data_processing/" />
<meta property="og:title" content="Data Processing (Help Wanted)" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/data_processing/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Data Processing (Help Wanted)</h2>
</div>
<h2 id="help-wanted">Help wanted</h2><p>Please follow the <a href="https://github.com/clojure-doc/clojure-doc.github.io/tree/source#how-to-contribute">instructions</a> on how to contribute and start writing over <a href="https://github.com/clojure-doc/clojure-doc.github.io/blob/source/content/md/articles/ecosystem/data_processing.md">here</a></p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p>
<div id="prev-next">
<a href="../generating_documentation/index.html">&laquo; Generating Documentation</a>
||
<a href="../web_development/index.html">Web Development (Overview) &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,231 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Generating Documentation</title>
<meta name="description" content="This guide notes some commonly-used tools for generating project
documentation.This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.">
<meta property="og:description" content="This guide notes some commonly-used tools for generating project
documentation.This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/generating_documentation/" />
<meta property="og:title" content="Generating Documentation" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/generating_documentation/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Generating Documentation</h2>
</div>
<p>This guide notes some commonly-used tools for generating project
documentation.</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.4.</p><h2 id="overview">Overview</h2><p>Projects commonly (hopefully?) have at least two types of
documentation:</p><ul><li>standalone
<a href="http://en.wikipedia.org/wiki/Markdown">markdown</a>-formatted docs
in the project's doc directory</li><li>docstrings</li></ul><p>There are a number of tools for generating handsome API docs from
docstrings and other project metadata.</p><h2 id="codox">Codox</h2><p>If you'd like to generate nice-looking html API docs for your library,
use <a href="https://github.com/weavejester/codox">codox</a>. Usage instructions
are in the codox readme. Running codox (it's a lein plug-in and is run
via <code>lein codox</code> in your project) will create a "doc" subdirectory
containing the resulting html.</p><h2 id="marginalia">Marginalia</h2><p>If you'd like to render API docs side-by-side with the source code
it's documenting, use <a href="https://github.com/fogus/lein-marginalia">the marginalia lein
plug-in</a>. Usage instructions
are in the readme.</p><h2 id="cadastre">Cadastre</h2><p>If you'd like to generate copious raw data from a project (which
includes docstrings as well as other metadata), have a look at
<a href="https://github.com/dakrone/cadastre">cadastre</a>.</p>
<div id="prev-next">
<a href="../libraries_authoring/index.html">&laquo; Library Development and Distribution</a>
||
<a href="../data_processing/index.html">Data Processing (Help Wanted) &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,310 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: java.jdbc - Getting Started</title>
<meta name="description" content="This guide is intended to help you the Clojure Contrib JDBC wrapper: clojure.java.jdbcA modern JDBC wrapper has since been written (by the same author/maintainer) -- read about next.jdbc on cljdoc.org">
<meta property="og:description" content="This guide is intended to help you the Clojure Contrib JDBC wrapper: clojure.java.jdbcA modern JDBC wrapper has since been written (by the same author/maintainer) -- read about next.jdbc on cljdoc.org">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/home/" />
<meta property="og:title" content="java.jdbc - Getting Started" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/home/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>java.jdbc - Getting Started</h2>
</div>
<p>This guide is intended to help you the Clojure Contrib JDBC wrapper: <code>clojure.java.jdbc</code></p><p><strong>A modern JDBC wrapper has since been written (by the same author/maintainer) -- read about <a href="https://clojure-doc.org/articles/ecosystem/java_jdbc/home/cljdoc.org/d/com.github.seancorfield/next.jdbc/"><code>next.jdbc</code> on cljdoc.org</a></strong></p><h2 id="contents">Contents</h2><ul><li><a href="home.html">Overview</a></li><li><a href="using_sql.html">Using SQL</a></li><li><a href="using_ddl.html">Using DDL</a></li><li><a href="reusing_connections.html">Reusing Connections</a></li></ul><h2 id="overview">Overview</h2><p><code>java.jdbc</code> is intended to be a low-level Clojure wrapper around various Java
JDBC drivers and supports a wide range of databases. The <a href="https://github.com/clojure/java.jdbc/"><code>java.jdbc</code> source is
on GitHub</a> and there is a dedicated <a href="https://groups.google.com/forum/#!forum/clojure-java-jdbc">java.jdbc mailing
list</a>. The detailed <a href="http://clojure.github.io/java.jdbc/"><code>java.jdbc</code> reference</a> is
automatically generated from the <code>java.jdbc</code> source.</p><p>Generally, when using <code>java.jdbc</code>, you will set up a data source as a "database
spec" and pass that to the various CRUD (create, read, update, delete)
functions that <code>java.jdbc</code> provides. These operations are detailed within the
<a href="using_sql.html">Using SQL</a> page, but a quick overview is provided by the
walkthrough below.</p><p>By default, each operation opens a connection and executes the SQL inside a
transaction. You can also run multiple operations against the same connection,
either within a transaction or via connection pooling, or just with a shared
connection. You can read more about reusing connections on the <a href="reusing_connections.html">Reusing
Connections</a> page.</p><h2 id="higher-level-dsl-and-migration-libraries">Higher-level DSL and migration libraries</h2><p>If you need more abstraction than the <code>java.jdbc</code> wrapper provides, you may want
to consider using a library that provides a DSL. All of the following libraries
are built on top of <code>java.jdbc</code> and provide such abstraction:</p><ul><li><a href="https://github.com/jkk/honeysql">HoneySQL</a></li><li><a href="https://github.com/r0man/sqlingvo">SQLingvo</a></li><li><a href="http://sqlkorma.com">Korma</a></li><li><a href="https://github.com/walkable-server/walkable">Walkable</a></li></ul><p>In particular, <a href="http://sqlkorma.com">Korma</a> goes beyond a SQL DSL to provide "entities" and
"relationships" (in the style of classical Object-Relational Mappers, but
without the pain).</p><p>Another common need with SQL is for database migration libraries. Some of the
more popular options are:</p><ul><li><a href="https://github.com/macourtney/drift">Drift</a></li><li><a href="https://github.com/pjstadig/migratus">Migratus</a></li><li><a href="https://github.com/weavejester/ragtime">Ragtime</a></li></ul><h2 id="a-brief-javajdbc-walkthrough">A brief <code>java.jdbc</code> walkthrough</h2><h3 id="setting-up-a-data-source">Setting up a data source</h3><p>A "database spec" is a Clojure map that specifies how to access the data
source. Most commonly, you specify the database type, the database name,
and the username and password. For example,</p><pre><code class="clojure">(def db-spec
{:dbtype "mysql"
:dbname "mydb"
:user "myaccount"
:password "secret"})
</code></pre><p>See <a href="home.html#database-support"><strong>Database Support</strong></a> below for a complete list of
databases and drivers supported by <code>java.jdbc</code> out of the box.</p><h3 id="a-hello-world-query">A "Hello World" Query</h3><p>Querying the database can be as simple as:</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(jdbc/query db-spec ["SELECT 3*5 AS result"])
=&gt; {:result 15}
</code></pre><p>Of course, we will want to do more with our database than have it perform
simple calculations. Once we can successfully connect to it, we will likely
want to create tables and manipulate data.</p><h3 id="creating-tables">Creating tables</h3><p><code>java.jdbc</code> provides <code>create-table-ddl</code> and <code>drop-table-ddl</code> to generate basic
<code>CREATE TABLE</code> and <code>DROP TABLE</code> DDL strings. Anything beyond that can be
constructed manually as a string.</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(def fruit-table-ddl
(jdbc/create-table-ddl :fruit
[[:name "varchar(32)"]
[:appearance "varchar(32)"]
[:cost :int]
[:grade :real]]))
</code></pre><p>We can use the function <code>db-do-commands</code> to create our table and indexes in a
single transaction:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec
[fruit-table-ddl
"CREATE INDEX name_ix ON fruit ( name );"])
</code></pre><p>For more details on DDL functionality within <code>java.jdbc</code>, see the <a href="using_ddl.html">Using DDL and
Metadata Guide</a>.</p><h3 id="querying-the-database">Querying the database</h3><p>The four basic CRUD operations <code>java.jdbc</code> provides are:</p><pre><code class="clojure">(jdbc/insert! db-spec :table {:col1 42 :col2 "123"}) ;; Create
(jdbc/query db-spec ["SELECT * FROM table WHERE id = ?" 13]) ;; Read
(jdbc/update! db-spec :table {:col1 77 :col2 "456"} ["id = ?" 13]) ;; Update
(jdbc/delete! db-spec :table ["id = ?" 13]) ;; Delete
</code></pre><p>The table name can be specified as a string or a keyword.</p><p><code>insert!</code> takes a single record in hash map form to insert. <code>insert!</code> can also
take a vector of column names (as strings or keywords), followed by a vector of
column values to insert into those respective columns, much like an <code>INSERT</code>
statement in SQL. Entries in the map that have the value <code>nil</code> will cause
<code>NULL</code> values to be inserted into the corresponding columns.</p><p>If you wish to insert multiple rows (in hash map form) at once, you can use
<code>insert-multi!</code>; however, <code>insert-multi!</code> will write a separate insertion
statement for each row, so it is suggested you use the column-based form of
<code>insert-multi!</code> over the row-based form. Passing multiple column values to
<code>insert-multi!</code> will generate a single batched insertion statement and yield
better performance.</p><p><code>query</code> allows us to run selection queries on the database. Since you provide
the query string directly, you have as much flexibility as you like to perform
complex queries.</p><p><code>update!</code> takes a map of columns to update, with their new values, and a SQL
clause used to select which rows to update (prepended by <code>WHERE</code> in the
generated SQL). As with <code>insert!</code>, <code>nil</code> values in the map cause the
corresponding columns to be set to <code>NULL</code>.</p><p><code>delete!</code> takes a SQL clause used to select which rows to delete, similar to
<code>update!</code>.</p><p>By default, the table name and column names are converted to strings
corresponding to the keyword names in the underlying SQL. We can control how we
transform keywords into SQL names using an optional <code>:entities</code> argument which
is described in more detail in the <a href="using_sql.html">Using SQL</a> section.</p><h3 id="dropping-our-tables">Dropping our tables</h3><p>To clean out the database from our example, we can generate a the command to
drop the fruit table:</p><pre><code class="clojure">(def drop-fruit-table-ddl (jdbc/drop-table-ddl :fruit))
</code></pre><p>Ensure you tear down your tables and indexes in the opposite order of creation:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec
["DROP INDEX name_ix;"
drop-fruit-table-ddl])
</code></pre><p>These are all the commands we need to write a simple migration for our database!</p><h2 id="database-support">Database Support</h2><p>Out of the box, <code>java.jdbc</code> understands the following <code>:dbtype</code> values (with
their default class names):</p><ul><li><code>"derby"</code> - <code>org.apache.derby.jdbc.EmbeddedDriver</code></li><li><code>"h2"</code> - <code>org.h2.Driver</code></li><li><code>"h2:mem"</code> - <code>org.h2.Driver</code></li><li><code>"hsqldb"</code> or <code>"hsql"</code> - <code>org.hsqldb.jdbcDriver</code></li><li><code>"jtds:sqlserver"</code> or <code>"jtds"</code> - <code>net.sourceforge.jtds.jdbc.Driver</code></li><li><code>"mysql"</code> - <code>com.mysql.jdbc.Driver</code></li><li><code>"oracle:oci"</code> - <code>oracle.jdbc.OracleDriver</code></li><li><code>"oracle:thin"</code> or <code>"oracle"</code> - <code>oracle.jdbc.OracleDriver</code></li><li><code>"postgresql"</code> or <code>"postgres"</code> - <code>org.postgresql.Driver</code></li><li><code>"pgsql"</code> - <code>com.impossibl.postgres.jdbc.PGDriver</code></li><li><code>"redshift"</code> - <code>com.amazon.redshift.jdbc.Driver</code></li><li><code>"sqlite"</code> - <code>org.sqlite.JDBC</code></li><li><code>"sqlserver"</code> - <code>"mssql"</code> - <code>com.microsoft.sqlserver.jdbc.SQLServerDriver</code></li></ul><p>You must specify the appropriate JDBC driver dependency in your project -- these
drivers are not included with <code>java.jdbc</code>.</p><p>You can overide the default class name by specifying <code>:classname</code> as well as
<code>:dbtype</code>.</p><p>For databases that require a hostname or IP address, <code>java.jdbc</code> assumes
<code>"127.0.0.1"</code> but that can be overidden with the <code>:host</code> option.</p><p>For databases that require a port, <code>java.jdbc</code> has the following defaults,
which can be overridden with the <code>:port</code> option:</p><ul><li>Microsoft SQL Server - 1433</li><li>MySQL - 3306</li><li>Oracle - 1521</li><li>PostgreSQL - 5432</li></ul><p>Some databases require a different format for the "database spec". Here is an example
that was required for an in-memory <a href="http://www.h2database.com">H2 database</a> prior
to <code>java.jdbc</code> release 0.7.6:</p><pre><code class="clojure">(def db-spec
{:classname "org.h2.Driver"
:subprotocol "h2:mem" ; the prefix `jdbc:` is added automatically
:subname "demo;DB_CLOSE_DELAY=-1" ; `;DB_CLOSE_DELAY=-1` very important!!!
; http://www.h2database.com/html/features.html#in_memory_databases
:user "sa" ; default "system admin" user
:password "" ; default password =&gt; empty string
})
</code></pre><p>This is the most general form of database spec, that allows you to control each
piece of the JDBC connection URL that would be created.</p><p>Note: as of <code>java.jdbc</code> 0.7.6, in-memory H2 databases are supported directly
via the simple spec form:</p><pre><code class="clojure">(def db-spec
{:dbtype "h2:mem"
:dbname "mydb"})
</code></pre><p>For file-based databases, such as H2, Derby, SQLite etc, the <code>:dbname</code> will
specify the filename:</p><pre><code class="clojure">(def db-spec
{:dbtype "h2"
:dbname "/path/to/my/database"})
</code></pre><h2 id="more-detailed-javajdbc-documentation">More detailed <code>java.jdbc</code> documentation</h2><ul><li><a href="using_sql.html">Using SQL:</a> a more detailed guide on using SQL with <code>java.jdbc</code></li><li><a href="using_ddl.html">Using DDL:</a> how to create your tables using the <code>java.jdbc</code> DDL</li><li><a href="reusing_connections.html">Reusing Connections:</a> how to reuse your database
connections</li></ul>
<div id="prev-next">
<a href="../../cookbooks/middleware/index.html">&laquo; Middleware in Clojure</a>
||
<a href="using_sql.html">java.jdbc - Manipulating data with SQL &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="home.html">java.jdbc - Getting Started</a></li>
<li><a href="using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,310 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: java.jdbc - Getting Started</title>
<meta name="description" content="This guide is intended to help you the Clojure Contrib JDBC wrapper: clojure.java.jdbcA modern JDBC wrapper has since been written (by the same author/maintainer) -- read about next.jdbc on cljdoc.org">
<meta property="og:description" content="This guide is intended to help you the Clojure Contrib JDBC wrapper: clojure.java.jdbcA modern JDBC wrapper has since been written (by the same author/maintainer) -- read about next.jdbc on cljdoc.org">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/home/" />
<meta property="og:title" content="java.jdbc - Getting Started" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/home/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>java.jdbc - Getting Started</h2>
</div>
<p>This guide is intended to help you the Clojure Contrib JDBC wrapper: <code>clojure.java.jdbc</code></p><p><strong>A modern JDBC wrapper has since been written (by the same author/maintainer) -- read about <a href="https://clojure-doc.org/articles/ecosystem/java_jdbc/home/cljdoc.org/d/com.github.seancorfield/next.jdbc/"><code>next.jdbc</code> on cljdoc.org</a></strong></p><h2 id="contents">Contents</h2><ul><li><a href="../home.html">Overview</a></li><li><a href="../using_sql.html">Using SQL</a></li><li><a href="../using_ddl.html">Using DDL</a></li><li><a href="../reusing_connections.html">Reusing Connections</a></li></ul><h2 id="overview">Overview</h2><p><code>java.jdbc</code> is intended to be a low-level Clojure wrapper around various Java
JDBC drivers and supports a wide range of databases. The <a href="https://github.com/clojure/java.jdbc/"><code>java.jdbc</code> source is
on GitHub</a> and there is a dedicated <a href="https://groups.google.com/forum/#!forum/clojure-java-jdbc">java.jdbc mailing
list</a>. The detailed <a href="http://clojure.github.io/java.jdbc/"><code>java.jdbc</code> reference</a> is
automatically generated from the <code>java.jdbc</code> source.</p><p>Generally, when using <code>java.jdbc</code>, you will set up a data source as a "database
spec" and pass that to the various CRUD (create, read, update, delete)
functions that <code>java.jdbc</code> provides. These operations are detailed within the
<a href="../using_sql.html">Using SQL</a> page, but a quick overview is provided by the
walkthrough below.</p><p>By default, each operation opens a connection and executes the SQL inside a
transaction. You can also run multiple operations against the same connection,
either within a transaction or via connection pooling, or just with a shared
connection. You can read more about reusing connections on the <a href="../reusing_connections.html">Reusing
Connections</a> page.</p><h2 id="higher-level-dsl-and-migration-libraries">Higher-level DSL and migration libraries</h2><p>If you need more abstraction than the <code>java.jdbc</code> wrapper provides, you may want
to consider using a library that provides a DSL. All of the following libraries
are built on top of <code>java.jdbc</code> and provide such abstraction:</p><ul><li><a href="https://github.com/jkk/honeysql">HoneySQL</a></li><li><a href="https://github.com/r0man/sqlingvo">SQLingvo</a></li><li><a href="http://sqlkorma.com">Korma</a></li><li><a href="https://github.com/walkable-server/walkable">Walkable</a></li></ul><p>In particular, <a href="http://sqlkorma.com">Korma</a> goes beyond a SQL DSL to provide "entities" and
"relationships" (in the style of classical Object-Relational Mappers, but
without the pain).</p><p>Another common need with SQL is for database migration libraries. Some of the
more popular options are:</p><ul><li><a href="https://github.com/macourtney/drift">Drift</a></li><li><a href="https://github.com/pjstadig/migratus">Migratus</a></li><li><a href="https://github.com/weavejester/ragtime">Ragtime</a></li></ul><h2 id="a-brief-javajdbc-walkthrough">A brief <code>java.jdbc</code> walkthrough</h2><h3 id="setting-up-a-data-source">Setting up a data source</h3><p>A "database spec" is a Clojure map that specifies how to access the data
source. Most commonly, you specify the database type, the database name,
and the username and password. For example,</p><pre><code class="clojure">(def db-spec
{:dbtype "mysql"
:dbname "mydb"
:user "myaccount"
:password "secret"})
</code></pre><p>See <a href="../home.html#database-support"><strong>Database Support</strong></a> below for a complete list of
databases and drivers supported by <code>java.jdbc</code> out of the box.</p><h3 id="a-hello-world-query">A "Hello World" Query</h3><p>Querying the database can be as simple as:</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(jdbc/query db-spec ["SELECT 3*5 AS result"])
=&gt; {:result 15}
</code></pre><p>Of course, we will want to do more with our database than have it perform
simple calculations. Once we can successfully connect to it, we will likely
want to create tables and manipulate data.</p><h3 id="creating-tables">Creating tables</h3><p><code>java.jdbc</code> provides <code>create-table-ddl</code> and <code>drop-table-ddl</code> to generate basic
<code>CREATE TABLE</code> and <code>DROP TABLE</code> DDL strings. Anything beyond that can be
constructed manually as a string.</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(def fruit-table-ddl
(jdbc/create-table-ddl :fruit
[[:name "varchar(32)"]
[:appearance "varchar(32)"]
[:cost :int]
[:grade :real]]))
</code></pre><p>We can use the function <code>db-do-commands</code> to create our table and indexes in a
single transaction:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec
[fruit-table-ddl
"CREATE INDEX name_ix ON fruit ( name );"])
</code></pre><p>For more details on DDL functionality within <code>java.jdbc</code>, see the <a href="../using_ddl.html">Using DDL and
Metadata Guide</a>.</p><h3 id="querying-the-database">Querying the database</h3><p>The four basic CRUD operations <code>java.jdbc</code> provides are:</p><pre><code class="clojure">(jdbc/insert! db-spec :table {:col1 42 :col2 "123"}) ;; Create
(jdbc/query db-spec ["SELECT * FROM table WHERE id = ?" 13]) ;; Read
(jdbc/update! db-spec :table {:col1 77 :col2 "456"} ["id = ?" 13]) ;; Update
(jdbc/delete! db-spec :table ["id = ?" 13]) ;; Delete
</code></pre><p>The table name can be specified as a string or a keyword.</p><p><code>insert!</code> takes a single record in hash map form to insert. <code>insert!</code> can also
take a vector of column names (as strings or keywords), followed by a vector of
column values to insert into those respective columns, much like an <code>INSERT</code>
statement in SQL. Entries in the map that have the value <code>nil</code> will cause
<code>NULL</code> values to be inserted into the corresponding columns.</p><p>If you wish to insert multiple rows (in hash map form) at once, you can use
<code>insert-multi!</code>; however, <code>insert-multi!</code> will write a separate insertion
statement for each row, so it is suggested you use the column-based form of
<code>insert-multi!</code> over the row-based form. Passing multiple column values to
<code>insert-multi!</code> will generate a single batched insertion statement and yield
better performance.</p><p><code>query</code> allows us to run selection queries on the database. Since you provide
the query string directly, you have as much flexibility as you like to perform
complex queries.</p><p><code>update!</code> takes a map of columns to update, with their new values, and a SQL
clause used to select which rows to update (prepended by <code>WHERE</code> in the
generated SQL). As with <code>insert!</code>, <code>nil</code> values in the map cause the
corresponding columns to be set to <code>NULL</code>.</p><p><code>delete!</code> takes a SQL clause used to select which rows to delete, similar to
<code>update!</code>.</p><p>By default, the table name and column names are converted to strings
corresponding to the keyword names in the underlying SQL. We can control how we
transform keywords into SQL names using an optional <code>:entities</code> argument which
is described in more detail in the <a href="../using_sql.html">Using SQL</a> section.</p><h3 id="dropping-our-tables">Dropping our tables</h3><p>To clean out the database from our example, we can generate a the command to
drop the fruit table:</p><pre><code class="clojure">(def drop-fruit-table-ddl (jdbc/drop-table-ddl :fruit))
</code></pre><p>Ensure you tear down your tables and indexes in the opposite order of creation:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec
["DROP INDEX name_ix;"
drop-fruit-table-ddl])
</code></pre><p>These are all the commands we need to write a simple migration for our database!</p><h2 id="database-support">Database Support</h2><p>Out of the box, <code>java.jdbc</code> understands the following <code>:dbtype</code> values (with
their default class names):</p><ul><li><code>"derby"</code> - <code>org.apache.derby.jdbc.EmbeddedDriver</code></li><li><code>"h2"</code> - <code>org.h2.Driver</code></li><li><code>"h2:mem"</code> - <code>org.h2.Driver</code></li><li><code>"hsqldb"</code> or <code>"hsql"</code> - <code>org.hsqldb.jdbcDriver</code></li><li><code>"jtds:sqlserver"</code> or <code>"jtds"</code> - <code>net.sourceforge.jtds.jdbc.Driver</code></li><li><code>"mysql"</code> - <code>com.mysql.jdbc.Driver</code></li><li><code>"oracle:oci"</code> - <code>oracle.jdbc.OracleDriver</code></li><li><code>"oracle:thin"</code> or <code>"oracle"</code> - <code>oracle.jdbc.OracleDriver</code></li><li><code>"postgresql"</code> or <code>"postgres"</code> - <code>org.postgresql.Driver</code></li><li><code>"pgsql"</code> - <code>com.impossibl.postgres.jdbc.PGDriver</code></li><li><code>"redshift"</code> - <code>com.amazon.redshift.jdbc.Driver</code></li><li><code>"sqlite"</code> - <code>org.sqlite.JDBC</code></li><li><code>"sqlserver"</code> - <code>"mssql"</code> - <code>com.microsoft.sqlserver.jdbc.SQLServerDriver</code></li></ul><p>You must specify the appropriate JDBC driver dependency in your project -- these
drivers are not included with <code>java.jdbc</code>.</p><p>You can overide the default class name by specifying <code>:classname</code> as well as
<code>:dbtype</code>.</p><p>For databases that require a hostname or IP address, <code>java.jdbc</code> assumes
<code>"127.0.0.1"</code> but that can be overidden with the <code>:host</code> option.</p><p>For databases that require a port, <code>java.jdbc</code> has the following defaults,
which can be overridden with the <code>:port</code> option:</p><ul><li>Microsoft SQL Server - 1433</li><li>MySQL - 3306</li><li>Oracle - 1521</li><li>PostgreSQL - 5432</li></ul><p>Some databases require a different format for the "database spec". Here is an example
that was required for an in-memory <a href="http://www.h2database.com">H2 database</a> prior
to <code>java.jdbc</code> release 0.7.6:</p><pre><code class="clojure">(def db-spec
{:classname "org.h2.Driver"
:subprotocol "h2:mem" ; the prefix `jdbc:` is added automatically
:subname "demo;DB_CLOSE_DELAY=-1" ; `;DB_CLOSE_DELAY=-1` very important!!!
; http://www.h2database.com/html/features.html#in_memory_databases
:user "sa" ; default "system admin" user
:password "" ; default password =&gt; empty string
})
</code></pre><p>This is the most general form of database spec, that allows you to control each
piece of the JDBC connection URL that would be created.</p><p>Note: as of <code>java.jdbc</code> 0.7.6, in-memory H2 databases are supported directly
via the simple spec form:</p><pre><code class="clojure">(def db-spec
{:dbtype "h2:mem"
:dbname "mydb"})
</code></pre><p>For file-based databases, such as H2, Derby, SQLite etc, the <code>:dbname</code> will
specify the filename:</p><pre><code class="clojure">(def db-spec
{:dbtype "h2"
:dbname "/path/to/my/database"})
</code></pre><h2 id="more-detailed-javajdbc-documentation">More detailed <code>java.jdbc</code> documentation</h2><ul><li><a href="../using_sql.html">Using SQL:</a> a more detailed guide on using SQL with <code>java.jdbc</code></li><li><a href="../using_ddl.html">Using DDL:</a> how to create your tables using the <code>java.jdbc</code> DDL</li><li><a href="../reusing_connections.html">Reusing Connections:</a> how to reuse your database
connections</li></ul>
<div id="prev-next">
<a href="../../../cookbooks/middleware/index.html">&laquo; Middleware in Clojure</a>
||
<a href="../using_sql.html">java.jdbc - Manipulating data with SQL &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../home.html">java.jdbc - Getting Started</a></li>
<li><a href="../using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,289 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: java.jdbc - How to reuse database connections</title>
<meta name="description" content="Contents">
<meta property="og:description" content="Contents">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/reusing_connections/" />
<meta property="og:title" content="java.jdbc - How to reuse database connections" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/reusing_connections/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>java.jdbc - How to reuse database connections</h2>
</div>
<h2 id="contents">Contents</h2><ul><li><a href="home.html">Overview</a></li><li><a href="using_sql.html">Using SQL</a></li><li><a href="using_ddl.html">Using DDL</a></li><li><a href="reusing_connections.html">Reusing Connections</a></li></ul><h2 id="reusing-connections">Reusing Connections</h2><p>Since you rarely want every database operation to create a new connection,
there are two ways to reuse connections:</p><ul><li>Grouping Operations using <code>with-db-connection</code>: If you don't want to deal
with a connection pooling library, you can use this macro to automatically open a
connection and maintain it for a body of code, with each operation executed in its
own transaction, then close the connection.</li><li>Grouping Operations using <code>with-db-transaction</code>: If you want to execute multiple
operations in a single transaction, you can use this macro to automatically open a
connection, start a transaction, execute multiple operations, commit the transaction,
and then close the connection.</li><li>Connection Pooling: This is the recommended approach and is fairly
straightforward, with a number of connection pooling libraries available. See
<em>How To Use Connection Pooling</em> below for more information.</li></ul><h2 id="using-with-db-connection">Using <code>with-db-connection</code></h2><p>This macro provides the simplest way to reuse connections, without having to
add a dependency on an external connection pooling library:</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(jdbc/with-db-connection [db-con db-spec]
(let [;; fetch some rows using this connection
rows (jdbc/query db-con ["SELECT * FROM table WHERE id = ?" 42])]
;; insert a copy of the first row using the same connection
(jdbc/insert! db-con :table (dissoc (first rows) :id))))
</code></pre><p>The <code>query</code> and the <code>insert!</code> are each run in their own transaction and committed
if they succeed. If you want to run multiple operations in a single transaction
see the next section about <code>with-db-transaction</code>.</p><h2 id="using-with-db-transaction">Using <code>with-db-transaction</code></h2><p>This macro provides a way to reuse connections, committing or rolling back
multiple operations in a single transaction:</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(jdbc/with-db-transaction [t-con db-spec]
(let [;; fetch some rows using this connection
rows (jdbc/query t-con ["SELECT * FROM table WHERE id = ?" 42])]
;; insert a copy of the first row using the same connection
(jdbc/insert! t-con :table (dissoc (first rows) :id))))
</code></pre><p>If any operation inside <code>with-db-transaction</code> fails (throws an exception), then
all of the operations performed so far are rolled back. If all the operations
succeed, then the entire transaction is committed.</p><p>Transactions are not nested (since not all databases support that) so if this is
used another active transaction, the outer transaction (and connection) are used
as-is. If the isolation levels of the outer and inner transaction do not match
you will get an <code>IllegalStateException</code>.</p><p>See also <code>db-set-rollback-only!</code>, <code>db-unset-rollback-only!</code>, and <code>db-is-rollback-only</code>
for additional control over the commit/rollback behavior of the enclosing transaction.</p><h2 id="using-connection-pooling">Using Connection Pooling</h2><p><code>java.jdbc</code> does not provide connection pooling directly but it is relatively
easy to add to your project. There are several connection pooling libraries out
there, but here we will provide instructions for the popular <code>c3p0</code> library.</p><p>The basic idea is to add your chosen connection pooling library to your
project, import the appropriate class(es), define a function that consumes a
"database spec" and produces a map containing a <code>:datasource</code> key whose value
is the constructed pooled <code>DataSource</code> object, then use that hash map in place of your
bare <code>db-spec</code> variable. You are responsible for creating the pooled data
source object and passing the map containing it into any functions that need a
database connection.</p><h3 id="using-the-c3p0-library">Using the c3p0 library</h3><p>For more information on c3p0, consult the <a href="http://www.mchange.com/projects/c3p0/">c3p0
documentation</a>.</p><p>If you're using Leiningen, you can add the following to your dependencies:</p><pre><code class="clojure">[com.mchange/c3p0 "0.9.5.2"] ;; check the documentation for latest version
</code></pre><p>For a Maven-based project, you would add:</p><pre><code class="xml">&lt;dependency&gt;
&lt;groupId&gt;com.mchange&lt;/groupId&gt;
&lt;artifactId&gt;c3p0&lt;/artifactId&gt;
&lt;version&gt;0.9.5.2&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><h3 id="create-the-pooled-datasource-from-your-db-spec">Create the pooled datasource from your db-spec</h3><p>Define your <code>db-spec</code> using the long form, for example (for MySQL):</p><pre><code class="clojure">(def db-spec
{:classname "com.mysql.jdbc.Driver"
:subprotocol "mysql"
:subname "//127.0.0.1:3306/mydb"
:user "myaccount"
:password "secret"})
</code></pre><p>We have to use the long form here because c3p0 operates on the class name, subprotocol,
and subname elements. Of course, you don't really need to define a <code>db-spec</code> here
because you're not going to use it with <code>java.jdbc</code> directly, only with c3p0.</p><p>Import the c3p0 class as part of your namespace declaration, for example:</p><pre><code class="clojure">(ns example.db
(:import (com.mchange.v2.c3p0 ComboPooledDataSource)))
</code></pre><p>Define a function that creates a pooled datasource:</p><pre><code class="clojure">(defn pool
[spec]
(let [cpds (doto (ComboPooledDataSource.)
(.setDriverClass (:classname spec))
(.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
(.setUser (:user spec))
(.setPassword (:password spec))
;; expire excess connections after 30 minutes of inactivity:
(.setMaxIdleTimeExcessConnections (* 30 60))
;; expire connections after 3 hours of inactivity:
(.setMaxIdleTime (* 3 60 60)))]
{:datasource cpds}))
</code></pre><p>Now you can create a single connection pool:</p><pre><code class="clojure">(def pooled-db (delay (pool db-spec)))
(defn db-connection [] @pooled-db)
</code></pre><p>And then call <code>(db-connection)</code> wherever you need access to it. If you're using
a <a href="https://github.com/stuartsierra/component">component</a> lifecycle for your
application, you won't need <code>pooled-db</code> or <code>db-connection</code>. You'll just create
<code>(pool db-spec)</code> as part of your application's initialization and pass it
around as part of your system configuration.</p>
<div id="prev-next">
<a href="using_ddl.html">&laquo; java.jdbc - Using DDL and Metadata</a>
||
<a href="../core_typed/home/index.html">core.typed - User Documentation Home &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="home.html">java.jdbc - Getting Started</a></li>
<li><a href="using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,289 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: java.jdbc - How to reuse database connections</title>
<meta name="description" content="Contents">
<meta property="og:description" content="Contents">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/reusing_connections/" />
<meta property="og:title" content="java.jdbc - How to reuse database connections" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/reusing_connections/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>java.jdbc - How to reuse database connections</h2>
</div>
<h2 id="contents">Contents</h2><ul><li><a href="../home.html">Overview</a></li><li><a href="../using_sql.html">Using SQL</a></li><li><a href="../using_ddl.html">Using DDL</a></li><li><a href="../reusing_connections.html">Reusing Connections</a></li></ul><h2 id="reusing-connections">Reusing Connections</h2><p>Since you rarely want every database operation to create a new connection,
there are two ways to reuse connections:</p><ul><li>Grouping Operations using <code>with-db-connection</code>: If you don't want to deal
with a connection pooling library, you can use this macro to automatically open a
connection and maintain it for a body of code, with each operation executed in its
own transaction, then close the connection.</li><li>Grouping Operations using <code>with-db-transaction</code>: If you want to execute multiple
operations in a single transaction, you can use this macro to automatically open a
connection, start a transaction, execute multiple operations, commit the transaction,
and then close the connection.</li><li>Connection Pooling: This is the recommended approach and is fairly
straightforward, with a number of connection pooling libraries available. See
<em>How To Use Connection Pooling</em> below for more information.</li></ul><h2 id="using-with-db-connection">Using <code>with-db-connection</code></h2><p>This macro provides the simplest way to reuse connections, without having to
add a dependency on an external connection pooling library:</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(jdbc/with-db-connection [db-con db-spec]
(let [;; fetch some rows using this connection
rows (jdbc/query db-con ["SELECT * FROM table WHERE id = ?" 42])]
;; insert a copy of the first row using the same connection
(jdbc/insert! db-con :table (dissoc (first rows) :id))))
</code></pre><p>The <code>query</code> and the <code>insert!</code> are each run in their own transaction and committed
if they succeed. If you want to run multiple operations in a single transaction
see the next section about <code>with-db-transaction</code>.</p><h2 id="using-with-db-transaction">Using <code>with-db-transaction</code></h2><p>This macro provides a way to reuse connections, committing or rolling back
multiple operations in a single transaction:</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(jdbc/with-db-transaction [t-con db-spec]
(let [;; fetch some rows using this connection
rows (jdbc/query t-con ["SELECT * FROM table WHERE id = ?" 42])]
;; insert a copy of the first row using the same connection
(jdbc/insert! t-con :table (dissoc (first rows) :id))))
</code></pre><p>If any operation inside <code>with-db-transaction</code> fails (throws an exception), then
all of the operations performed so far are rolled back. If all the operations
succeed, then the entire transaction is committed.</p><p>Transactions are not nested (since not all databases support that) so if this is
used another active transaction, the outer transaction (and connection) are used
as-is. If the isolation levels of the outer and inner transaction do not match
you will get an <code>IllegalStateException</code>.</p><p>See also <code>db-set-rollback-only!</code>, <code>db-unset-rollback-only!</code>, and <code>db-is-rollback-only</code>
for additional control over the commit/rollback behavior of the enclosing transaction.</p><h2 id="using-connection-pooling">Using Connection Pooling</h2><p><code>java.jdbc</code> does not provide connection pooling directly but it is relatively
easy to add to your project. There are several connection pooling libraries out
there, but here we will provide instructions for the popular <code>c3p0</code> library.</p><p>The basic idea is to add your chosen connection pooling library to your
project, import the appropriate class(es), define a function that consumes a
"database spec" and produces a map containing a <code>:datasource</code> key whose value
is the constructed pooled <code>DataSource</code> object, then use that hash map in place of your
bare <code>db-spec</code> variable. You are responsible for creating the pooled data
source object and passing the map containing it into any functions that need a
database connection.</p><h3 id="using-the-c3p0-library">Using the c3p0 library</h3><p>For more information on c3p0, consult the <a href="http://www.mchange.com/projects/c3p0/">c3p0
documentation</a>.</p><p>If you're using Leiningen, you can add the following to your dependencies:</p><pre><code class="clojure">[com.mchange/c3p0 "0.9.5.2"] ;; check the documentation for latest version
</code></pre><p>For a Maven-based project, you would add:</p><pre><code class="xml">&lt;dependency&gt;
&lt;groupId&gt;com.mchange&lt;/groupId&gt;
&lt;artifactId&gt;c3p0&lt;/artifactId&gt;
&lt;version&gt;0.9.5.2&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><h3 id="create-the-pooled-datasource-from-your-db-spec">Create the pooled datasource from your db-spec</h3><p>Define your <code>db-spec</code> using the long form, for example (for MySQL):</p><pre><code class="clojure">(def db-spec
{:classname "com.mysql.jdbc.Driver"
:subprotocol "mysql"
:subname "//127.0.0.1:3306/mydb"
:user "myaccount"
:password "secret"})
</code></pre><p>We have to use the long form here because c3p0 operates on the class name, subprotocol,
and subname elements. Of course, you don't really need to define a <code>db-spec</code> here
because you're not going to use it with <code>java.jdbc</code> directly, only with c3p0.</p><p>Import the c3p0 class as part of your namespace declaration, for example:</p><pre><code class="clojure">(ns example.db
(:import (com.mchange.v2.c3p0 ComboPooledDataSource)))
</code></pre><p>Define a function that creates a pooled datasource:</p><pre><code class="clojure">(defn pool
[spec]
(let [cpds (doto (ComboPooledDataSource.)
(.setDriverClass (:classname spec))
(.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
(.setUser (:user spec))
(.setPassword (:password spec))
;; expire excess connections after 30 minutes of inactivity:
(.setMaxIdleTimeExcessConnections (* 30 60))
;; expire connections after 3 hours of inactivity:
(.setMaxIdleTime (* 3 60 60)))]
{:datasource cpds}))
</code></pre><p>Now you can create a single connection pool:</p><pre><code class="clojure">(def pooled-db (delay (pool db-spec)))
(defn db-connection [] @pooled-db)
</code></pre><p>And then call <code>(db-connection)</code> wherever you need access to it. If you're using
a <a href="https://github.com/stuartsierra/component">component</a> lifecycle for your
application, you won't need <code>pooled-db</code> or <code>db-connection</code>. You'll just create
<code>(pool db-spec)</code> as part of your application's initialization and pass it
around as part of your system configuration.</p>
<div id="prev-next">
<a href="../using_ddl.html">&laquo; java.jdbc - Using DDL and Metadata</a>
||
<a href="../../core_typed/home/index.html">core.typed - User Documentation Home &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../home.html">java.jdbc - Getting Started</a></li>
<li><a href="../using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,249 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: java.jdbc - Using DDL and Metadata</title>
<meta name="description" content="Contents">
<meta property="og:description" content="Contents">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/using_ddl/" />
<meta property="og:title" content="java.jdbc - Using DDL and Metadata" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/using_ddl/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>java.jdbc - Using DDL and Metadata</h2>
</div>
<h2 id="contents">Contents</h2><ul><li><a href="home.html">Overview</a></li><li><a href="using_sql.html">Using SQL</a></li><li><a href="using_ddl.html">Using DDL</a></li><li><a href="reusing_connections.html">Reusing Connections</a></li></ul><h2 id="using-ddl">Using DDL</h2><p>DDL operations can be executed using the <code>db-do-commands</code> function. The general
approach is:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec [sql-command-1 sql-command-2 .. sql-command-n])
</code></pre><p>The commands are executed as a single, batched statement, wrapped in a
transaction. If you want to avoid the transaction, use this approach:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec false [sql-command-1 sql-command-2 .. sql-command-n])
</code></pre><p>This is necessary for some databases that do not allow DDL operations to be
wrapped in a transaction.</p><h3 id="creating-tables">Creating tables</h3><p>For the common operations of creating and dropping tables, <code>java.jdbc</code> provides a
little assistance that recognizes <code>:entities</code> so you can use keywords (or
strings) and have your chosen naming strategy applied, just as you can for
several of the SQL functions.</p><pre><code class="clojure">(jdbc/create-table-ddl :fruit
[[:name "varchar(32)" :primary :key]
[:appearance "varchar(32)"]
[:cost :int]
[:grade :real]]
{:table-spec "ENGINE=InnoDB"
:entities clojure.string/upper-case})
</code></pre><p>This will generate:</p><pre><code class="clojure">CREATE TABLE FRUIT
(NAME varchar(32) primary key,
APPEARANCE varchar(32),
COST int,
GRADE real) ENGINE=InnoDB
</code></pre><p>which you can pass to <code>db-do-commands</code>.</p><p><code>create-table-ddl</code> also supports a <code>conditional?</code> option which can be a simple
<code>Boolean</code>, which, if <code>true</code>, will add <code>IF NOT EXISTS</code> before the table name. If
that syntax doesn't work for your database, you can pass a string that will be
used instead. If that isn't enough, you can pass a function of two arguments:
the first argument will be the table name and the second argument will be the
DDL string (this approach is needed for Microsoft SQL Server).</p><h3 id="dropping-tables">Dropping tables</h3><p>Similarly there is a <code>drop-table-ddl</code> function which takes a table name and an
optional <code>:entities</code> option to generate DDL to drop a table.</p><pre><code class="clojure">(jdbc/drop-table-ddl :fruit) ; drop table fruit
(jdbc/drop-table-ddl :fruit {:entities clojure.string/upper-case}) ; drop table FRUIT
</code></pre><p>This will generate:</p><pre><code class="clojure">DROP TABLE FRUIT
</code></pre><p><code>drop-table-ddl</code> also supports a <code>conditional?</code> option which can be a simple
<code>Boolean</code>, which, if <code>true</code>, will add <code>IF EXISTS</code> before the table name. If
that syntax doesn't work for your database, you can pass a string that will be
used instead. If that isn't enough, you can pass a function of two arguments:
the first argument will be the table name and the second argument will be the
DDL string (this approach is needed for Microsoft SQL Server).</p><h2 id="accessing-metadata">Accessing metadata</h2><p><code>java.jdbc</code> provides two functions for working with database metadata:</p><ul><li><code>with-db-metadata</code> for creating an active metadata object backed by an open
connection</li><li><code>metadata-result</code> for turning metadata results into Clojure data structures</li></ul><p>For example:</p><pre><code class="clojure">(jdbc/with-db-metadata [md db-spec]
(jdbc/metadata-result (.getTables md nil nil nil (into-array ["TABLE" "VIEW"]))))
</code></pre><p>This returns a sequence of maps describing all the tables and views in the
current database. <code>metadata-result</code> only transforms <code>ResultSet</code> objects, other
results are returned as-is. <code>metadata-result</code> can also accept an options map
containing <code>:identifiers</code> and <code>:as-arrays?</code>, like the <code>query</code> function,
and those options control how the metatadata is transformed and/or returned.</p><p>Both <code>with-db-metadata</code> and <code>metadata-result</code> can accept an options hash map
which will be passed through various <code>java.jdbc</code> functions (<code>get-connections</code>
for the former and <code>result-set-seq</code> for the latter).</p>
<div id="prev-next">
<a href="using_sql.html">&laquo; java.jdbc - Manipulating data with SQL</a>
||
<a href="reusing_connections.html">java.jdbc - How to reuse database connections &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="home.html">java.jdbc - Getting Started</a></li>
<li><a href="using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,249 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: java.jdbc - Using DDL and Metadata</title>
<meta name="description" content="Contents">
<meta property="og:description" content="Contents">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/using_ddl/" />
<meta property="og:title" content="java.jdbc - Using DDL and Metadata" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/using_ddl/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>java.jdbc - Using DDL and Metadata</h2>
</div>
<h2 id="contents">Contents</h2><ul><li><a href="../home.html">Overview</a></li><li><a href="../using_sql.html">Using SQL</a></li><li><a href="../using_ddl.html">Using DDL</a></li><li><a href="../reusing_connections.html">Reusing Connections</a></li></ul><h2 id="using-ddl">Using DDL</h2><p>DDL operations can be executed using the <code>db-do-commands</code> function. The general
approach is:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec [sql-command-1 sql-command-2 .. sql-command-n])
</code></pre><p>The commands are executed as a single, batched statement, wrapped in a
transaction. If you want to avoid the transaction, use this approach:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec false [sql-command-1 sql-command-2 .. sql-command-n])
</code></pre><p>This is necessary for some databases that do not allow DDL operations to be
wrapped in a transaction.</p><h3 id="creating-tables">Creating tables</h3><p>For the common operations of creating and dropping tables, <code>java.jdbc</code> provides a
little assistance that recognizes <code>:entities</code> so you can use keywords (or
strings) and have your chosen naming strategy applied, just as you can for
several of the SQL functions.</p><pre><code class="clojure">(jdbc/create-table-ddl :fruit
[[:name "varchar(32)" :primary :key]
[:appearance "varchar(32)"]
[:cost :int]
[:grade :real]]
{:table-spec "ENGINE=InnoDB"
:entities clojure.string/upper-case})
</code></pre><p>This will generate:</p><pre><code class="clojure">CREATE TABLE FRUIT
(NAME varchar(32) primary key,
APPEARANCE varchar(32),
COST int,
GRADE real) ENGINE=InnoDB
</code></pre><p>which you can pass to <code>db-do-commands</code>.</p><p><code>create-table-ddl</code> also supports a <code>conditional?</code> option which can be a simple
<code>Boolean</code>, which, if <code>true</code>, will add <code>IF NOT EXISTS</code> before the table name. If
that syntax doesn't work for your database, you can pass a string that will be
used instead. If that isn't enough, you can pass a function of two arguments:
the first argument will be the table name and the second argument will be the
DDL string (this approach is needed for Microsoft SQL Server).</p><h3 id="dropping-tables">Dropping tables</h3><p>Similarly there is a <code>drop-table-ddl</code> function which takes a table name and an
optional <code>:entities</code> option to generate DDL to drop a table.</p><pre><code class="clojure">(jdbc/drop-table-ddl :fruit) ; drop table fruit
(jdbc/drop-table-ddl :fruit {:entities clojure.string/upper-case}) ; drop table FRUIT
</code></pre><p>This will generate:</p><pre><code class="clojure">DROP TABLE FRUIT
</code></pre><p><code>drop-table-ddl</code> also supports a <code>conditional?</code> option which can be a simple
<code>Boolean</code>, which, if <code>true</code>, will add <code>IF EXISTS</code> before the table name. If
that syntax doesn't work for your database, you can pass a string that will be
used instead. If that isn't enough, you can pass a function of two arguments:
the first argument will be the table name and the second argument will be the
DDL string (this approach is needed for Microsoft SQL Server).</p><h2 id="accessing-metadata">Accessing metadata</h2><p><code>java.jdbc</code> provides two functions for working with database metadata:</p><ul><li><code>with-db-metadata</code> for creating an active metadata object backed by an open
connection</li><li><code>metadata-result</code> for turning metadata results into Clojure data structures</li></ul><p>For example:</p><pre><code class="clojure">(jdbc/with-db-metadata [md db-spec]
(jdbc/metadata-result (.getTables md nil nil nil (into-array ["TABLE" "VIEW"]))))
</code></pre><p>This returns a sequence of maps describing all the tables and views in the
current database. <code>metadata-result</code> only transforms <code>ResultSet</code> objects, other
results are returned as-is. <code>metadata-result</code> can also accept an options map
containing <code>:identifiers</code> and <code>:as-arrays?</code>, like the <code>query</code> function,
and those options control how the metatadata is transformed and/or returned.</p><p>Both <code>with-db-metadata</code> and <code>metadata-result</code> can accept an options hash map
which will be passed through various <code>java.jdbc</code> functions (<code>get-connections</code>
for the former and <code>result-set-seq</code> for the latter).</p>
<div id="prev-next">
<a href="../using_sql.html">&laquo; java.jdbc - Manipulating data with SQL</a>
||
<a href="../reusing_connections.html">java.jdbc - How to reuse database connections &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../home.html">java.jdbc - Getting Started</a></li>
<li><a href="../using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,510 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: java.jdbc - Manipulating data with SQL</title>
<meta name="description" content="Contents">
<meta property="og:description" content="Contents">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/using_sql/" />
<meta property="og:title" content="java.jdbc - Manipulating data with SQL" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/using_sql/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>java.jdbc - Manipulating data with SQL</h2>
</div>
<h2 id="contents">Contents</h2><ul><li><a href="home.html">Overview</a></li><li><a href="using_sql.html">Using SQL</a></li><li><a href="using_ddl.html">Using DDL</a></li><li><a href="reusing_connections.html">Reusing Connections</a></li></ul><h2 id="using-sql">Using SQL</h2><p>Here are some examples of using <code>java.jdbc</code> to manipulate data with SQL.
These examples assume a simple table called <code>fruit</code> (see <a href="https://clojure-doc.org/articles/ecosystem/java_jdbc/using_sql/using_ddl/">Using DDL and
Metadata</a>). These examples all assume the following in your
<code>ns</code> declaration:</p><pre><code class="clojure">(:require [clojure.java.jdbc :as jdbc])
</code></pre><h2 id="reading-and-processing-rows">Reading and processing rows</h2><p><code>java.jdbc</code> provides a simple <code>query</code> function to allow you to read rows from
tables, as well as optionally performing processing on them at the same time.</p><h3 id="reading-rows">Reading rows</h3><p>To obtain a fully realized result set as a sequence of maps, you can use
<code>query</code> with a vector containing the SQL string and any parameters needed by
the SQL:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM fruit"])
;; ({:id 1 :name "Apple" :appearance "red" :cost 59 :grade 87}
;; {:id 2 :name "Banana" :appearance "yellow" :cost 29 :grade 92.2}
;; ...)
(jdbc/query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50])
;; ({:id 2 :name "Banana" :appearance "yellow" :cost 29 :grade 92.2}
;; ...)
</code></pre><p>You can also return the result set as a sequence of vectors. The first vector
will contain the column names, and each subsequent vector will represent a row
of data with values in the same order as the columns.</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:as-arrays? true})
;; ([:id :name :appearance :cost :grade]
;; [2 "Banana" "yellow" 29 92.2]
;; ...)
</code></pre><h3 id="processing-a-result-set-lazily">Processing a result set lazily</h3><p>Since <code>query</code> returns a fully realized result set, it can be difficult to
process very large results. Fortunately, <code>java.jdbc</code> provides a number of ways to process a
large result set lazily while the connection is open, either by passing a function via
the <code>:result-set-fn</code> option or, since release 0.7.0, via <code>reducible-query</code>.</p><p><strong><code>query</code> and <code>:result-set-fn</code></strong></p><p><em>If you are using release 0.7.0 or later, consider using <code>reducible-query</code> instead -- see below.</em></p><p>For <code>:result-set-fn</code>, the function you pass must force
realization of the result to avoid the connection closing while the result set
is still being processed. A <code>reduce</code>-based function is a good choice.</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:result-set-fn (fn [rs]
(reduce (fn [total row-map]
(+ total (:cost row-map)))
0 rs))})
;; produces the total cost of all the cheap fruits: 437
</code></pre><p>Of course, a simple sum like this could be computed directly in SQL instead:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT SUM(cost) FROM fruit WHERE cost &lt; ?" 50]
{:result-set-fn first})
;; {:sum(cost) 437}
</code></pre><p>We know we will only get one row back so passing <code>first</code> to <code>:result-set-fn</code> is
a quick way to get just that row.</p><p>Remember that if you also specify <code>:as-arrays? true</code>, your result set function
will be passed a sequence of vectors in which the first vector contains the
column names and subsequent vectors represent the values in the rows, matching
the order of the column names.</p><p><strong><code>reducible-query</code></strong></p><p>This is the recommended approach since release 0.7.0 but it does come with a few
restrictions:</p><p>You cannot use any of the following options that <code>query</code> accepts:
<code>as-arrays?</code>, <code>:explain</code>, <code>:explain-fn</code>, <code>:result-set-fn</code>, or <code>:row-fn</code>.</p><p>On the other hand, you have access to a much faster way to process result sets:
you can specify <code>:raw? true</code> and no conversion from Java's <code>ResultSet</code> to
Clojure's sequence of hash maps will be performed. In particular, it's as if you
specified <code>:identifiers identity :keywordize? false :qualifier nil</code>, and the
sequence representation of each row is not available. That means no <code>keys</code>,
no <code>vals</code>, no <code>seq</code> calls, just simple key lookup (for convenience, you can
still use keyword lookup for columns, but you can also call <code>get</code> with either a
string or a keyword).</p><p>So how does this work? <code>reducible-query</code> produces a <code>clojure.lang.IReduce</code> which,
when reduced with a function <code>f</code>, performs the query and reduces the <code>ResultSet</code>
using <code>f</code>, opening and closing the connection and/or transaction during the
reduction. For example:</p><pre><code class="clojure">;; our reducing function requires two arguments: we must provide initial val
(reduce (fn [total {:keys [cost]}] (+ total cost))
0
(jdbc/reducible-query db-spec
["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:raw? true}))
;; separating the key selection from the reducing function: we can omit val
(transduce (map :cost)
+ ; can be called with 0, 1, or 2 arguments!
(jdbc/reducible-query db-spec
["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:raw? true}))
;; 437
</code></pre><p>Since <code>reducible-query</code> doesn't actually run the query until you reduce its result,
you can create it once and run it as many times as you want. This will avoid the
overhead of option and parameter validation and handling for repeated reductions,
since those are performed just once in the call to <code>reducible-query</code>. Note that
the SQL parameters are fixed by that call, so this only works for running the
<em>identical</em> query multiple times.</p><p>A reducible companion to <code>result-set-seq</code> also exists, in case you already have
a Java <code>ResultSet</code> and want to create a <code>clojure.lang.IReduce</code>. <code>reducible-result-set</code>
accept almost the same options as <code>result-set-seq</code>: <code>identifiers</code>, <code>keywordize?</code>,
<code>qualifier</code>, and <code>read-columns</code>. It does not accept <code>as-arrays?</code> (for the same
reason that <code>reducible-query</code> does not). Unlike <code>result-set-seq</code>, which produces
a lazy sequence that can be consumed multiple times (with the first pass realizing
it for subsequent passes), <code>reducible-result-set</code> is reducible just once: the
underlying <code>ResultSet</code> is mutable and is consumed during the first reduction!</p><p>It should go without saying that both <code>reducible-query</code> and
<code>reducible-result-set</code> respect <code>reduced</code> / <code>reduced?</code>.</p><p><strong>Additional Options?</strong></p><p>Note: some databases require additional options to be passed in to ensure that
result sets are chunked and lazy. In particular, you may need to pass
<code>:auto-commit?</code>, set appropriately, as an option to whichever function will open your database
connection (<code>with-db-connection</code>, <code>with-db-transaction</code>, or the <code>query</code> / <code>reducible-query</code> itself
if you are passing a bare database spec and expecting <code>query</code> / <code>reducible-query</code> to open and close
the connection directly). You may also need to specify <code>:fetch-size</code>, <code>:result-type</code>,
and possibly other options -- consult your database's documentation for the JDBC
driver you are using.</p><h3 id="processing-each-row-lazily">Processing each row lazily</h3><p>As seen above, using <code>reduce</code>, <code>transduce</code>, etc with a <code>reducible-query</code> allow
you to easily and efficiently process each row as you process the entire
result set, but sometimes you just want a sequence of transformed rows.</p><p>We can process each row with the <code>:row-fn</code> option. Again, like with <code>:result-set-fn</code>,
we pass a function but this time it will be
invoked on each row, as the result set is realized.</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT name FROM fruit WHERE cost &lt; ?" 50]
{:row-fn :name})
;; ("Apple" "Banana" ...)
</code></pre><p>The result is still a fully realized sequence, but each row has been
transformed by the <code>:name</code> function you passed in.</p><p>You can combine this with <code>:result-set-fn</code> to simplify processing of result
sets:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:row-fn :cost
:result-set-fn (partial reduce +)})
;; produces the total cost of all the cheap fruits
</code></pre><p>or:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT SUM(cost) AS total FROM fruit WHERE cost &lt; ?" 50]
{:row-fn :total
:result-set-fn first})
;; produces the same result, via SQL
</code></pre><p>Here is an example that manipulates rows to add computed columns:</p><pre><code class="clojure">(defn add-tax [row] (assoc row :tax (* 0.08 (:cost row))))
(jdbc/query db-spec ["SELECT * FROM fruit"]
{:row-fn add-tax})
;; produces all the rows with a new :tax column added
</code></pre><p>All of the above can be achieved via <code>reducible-query</code> and the appropriate
reducing function and/or transducer, but with those simple row/result set
functions, the result is often longer / uglier:</p><pre><code class="clojure">(into [] (map :name) (jdbc/reducible-query db-spec ["SELECT name FROM fruit WHERE cost &lt; ?" 50]))
(transduce (map :cost) + (jdbc/reducible-query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50]))
;; :row-fn :total :result-set-fn first left as an exercise for the reader!
(into [] (map add-tax) (jdbc/reducible-query db-spec ["SELECT * FROM fruit"]))
</code></pre><p>If the result set is likely to be large and the reduction can use a <code>:raw? true</code>
result set, <code>reducible-query</code> may be worth the verbosity for the performance gain.</p><h2 id="inserting-data">Inserting data</h2><p>Rows (and partial rows) can be inserted easily using the <code>insert!</code> function.
You can insert a single row, or multiple rows. Depending on how you call
<code>insert!</code>, the insertion will be done either through multiple SQL statements or
through a single, batched SQL statement. That will also determine whether or
not you get back any generated keys.</p><p>If you need a more complex form of insertion, you can use <code>execute!</code> and, if
your database / driver supports it, you can pass <code>:return-keys</code> as an option
to get back the generated keys. As of <code>java.jdbc</code> 0.7.6, this can be a vector
of column names to return (for drivers that support that) or a simple Boolean.</p><h3 id="inserting-a-row">Inserting a row</h3><p>If you want to insert a single row (or partial row) and get back the generated
keys, you can use <code>insert!</code> and specify the columns and their values as a map.
This performs a single insert statement. A single-element sequence containing a
map of the generated keys will be returned.</p><pre><code class="clojure">(jdbc/insert! db-spec :fruit {:name "Pear" :appearance "green" :cost 99})
;; returns a database-specific map as the only element of a sequence, e.g.,
;; ({:generated_key 50}) might be returned for MySQL
</code></pre><p>Not all databases are able to return generated keys from an insert.</p><h3 id="inserting-multiple-rows">Inserting multiple rows</h3><p>There are two ways to insert multiple rows: as a sequence of maps, or as a
sequence of vectors. In the former case, multiple inserts will be performed and
a map of the generated keys will be returned for each insert (as a sequence).
In the latter case, a single, batched insert will be performed and a sequence
of row insert counts will be returned (generally a sequence of ones). The latter
approach is likely to be substantially faster if you are inserting a large number
of rows.</p><p>If you use <code>insert-multi!</code> and specify each row as a map of columns and their values,
then you can specify a mixture of complete and partial rows, and you will get
back the generated keys for each row (assuming the database has that
capability).</p><pre><code class="clojure">(jdbc/insert-multi! db-spec :fruit
[{:name "Pomegranate" :appearance "fresh" :cost 585}
{:name "Kiwifruit" :grade 93}])
;; returns a sequence of database-specific maps, e.g., for MySQL:
;; ({generated_key 51} {generated_key 52})
</code></pre><p>If you use <code>insert-multi!</code> and specify the columns you wish to insert followed by
each row as a vector of column values, then you must specify the same columns
in each row, and you will not get generated keys back, just row counts. If you
wish to insert complete rows, you may omit the column name vector (passing
<code>nil</code> instead) but your rows must match the natural order of columns in your
table so be careful!</p><pre><code class="clojure">(jdbc/insert-multi! db-spec :fruit
nil ; column names not supplied
[[1 "Apple" "red" 59 87]
[2 "Banana" "yellow" 29 92.2]
[3 "Peach" "fuzzy" 139 90.0]
[4 "Orange" "juicy" 89 88.6]])
;; (1 1 1 1) - row counts modified
</code></pre><p>It is generally safer to specify the columns you wish to insert so you can
control the order, and choose to omit certain columns:</p><pre><code class="clojure">(jdbc/insert-multi! db-spec :fruit
[:name :cost]
[["Mango" 722]
["Feijoa" 441]])
;; (1 1) - row counts modified
</code></pre><h2 id="updating-rows">Updating rows</h2><p>If you want to update simple column values in one or more rows based on a
simple SQL predicate, you can use <code>update!</code> with a map, representing the column
values to set, and a SQL predicate with parameters. If you need a more complex
form of update, you can use the <code>execute!</code> function with arbitrary SQL (and
parameters).</p><pre><code class="clojure">;; update fruit set cost = 49 where grade &lt; ?
(jdbc/update! db-spec :fruit
{:cost 49}
["grade &lt; ?" 75])
;; produces a sequence of the number of rows updated, e.g., (2)
</code></pre><p>For a more complex update:</p><pre><code class="clojure">(jdbc/execute! db-spec
["update fruit set cost = ( 2 * grade ) where grade &gt; ?" 50.0])
;; produces a sequence of the number of rows updated, e.g., (3)
</code></pre><h2 id="deleting-rows">Deleting rows</h2><p>If you want to delete any rows from a table that match a simple predicate, the
<code>delete!</code> function can be used.</p><pre><code class="clojure">(jdbc/delete! db-spec :fruit ["grade &lt; ?" 25.0])
;; produces a sequence of the number of rows deleted, e.g., (1)
</code></pre><p>You can also use <code>execute!</code> for deleting rows:</p><pre><code class="clojure">(jdbc/execute! db-spec ["DELETE FROM fruit WHERE grade &lt; ?" 25.0])
;; produces a sequence of the number of rows deleted, e.g., (1)
</code></pre><h2 id="using-transactions">Using transactions</h2><p>You can write multiple operations in a transaction to ensure they are either
all performed, or all rolled back.</p><pre><code class="clojure">(jdbc/with-db-transaction [t-con db-spec]
(jdbc/update! t-con :fruit
{:cost 49}
["grade &lt; ?" 75])
(jdbc/execute! t-con
["update fruit set cost = ( 2 * grade ) where grade &gt; ?" 50.0]))
</code></pre><p>The <code>with-db-transaction</code> macro creates a transaction-aware connection from the
database specification and that should be used in the body of the transaction
code.</p><p>You can specify the transaction isolation level as part of the
<code>with-db-transction</code> binding:</p><pre><code class="clojure">(jdbc/with-db-transaction [t-con db-spec {:isolation :serializable}]
...)
</code></pre><p>Possible values for <code>:isolation</code> are <code>:none</code>, <code>:read-committed</code>,
<code>:read-uncommitted</code>, <code>:repeatable-read</code>, and <code>:serializable</code>. Be aware that not
all databases support all isolation levels. Inside a transaction, you can call
<code>get-isolation-level</code> to return the current level.</p><p>In addition, you can also set the current transaction-aware connection to
rollback, and reset that setting, as well as test whether the connection is
currently set to rollback, using the following functions:</p><pre><code class="clojure">(jdbc/db-set-rollback-only! t-con) ; this transaction will rollback instead of commit
(jdbc/db-unset-rollback-only! t-con) ; this transaction will commit if successful
(jdbc/db-is-rollback-only t-con) ; returns true if transaction is set to rollback
</code></pre><h2 id="updating-or-inserting-rows-conditionally">Updating or Inserting rows conditionally</h2><p><code>java.jdbc</code> does not provide a built-in function for updating existing rows or
inserting a new row (the older API supported this but the logic was too
simplistic to be generally useful). If you need that functionality, it can
sometimes be done like this:</p><pre><code class="clojure">(defn update-or-insert!
"Updates columns or inserts a new row in the specified table"
[db table row where-clause]
(jdbc/with-db-transaction [t-con db]
(let [result (jdbc/update! t-con table row where-clause)]
(if (zero? (first result))
(jdbc/insert! t-con table row)
result))))
(update-or-insert! mysql-db :fruit
{:name "Cactus" :appearance "Spiky" :cost 2000}
["name = ?" "Cactus"])
;; inserts Cactus (assuming none exists)
(update-or-insert! mysql-db :fruit
{:name "Cactus" :appearance "Spiky" :cost 2500}
["name = ?" "Cactus"])
;; updates the Cactus we just inserted
</code></pre><p>If the <code>where-clause</code> does not uniquely identify a single row, this will update
multiple rows which might not be what you want, so be careful!</p><h2 id="exception-handling-and-transaction-rollback">Exception Handling and Transaction Rollback</h2><p>Transactions are rolled back if an exception is thrown, as shown in these
examples.</p><pre><code class="clojure">(jdbc/with-db-transaction [t-con db-spec]
(jdbc/insert-multi! t-con :fruit
[:name :appearance]
[["Grape" "yummy"]
["Pear" "bruised"]])
;; At this point the insert! call is complete, but the transaction is
;; not. The exception will cause it to roll back leaving the database
;; untouched.
(throw (Exception. "sql/test exception")))
</code></pre><p>As noted above, transactions can also be set explicitly to rollback instead of
commit:</p><pre><code class="clojure">(jdbc/with-db-transaction [t-con db-spec]
(prn "is-rollback-only" (jdbc/db-is-rollback-only t-con))
;; is-rollback-only false
(jdbc/db-set-rollback-only! t-con)
;; the following insert will be rolled back when the transaction ends:
(jdbc/insert!-multi t-con :fruit
[:name :appearance]
[["Grape" "yummy"]
["Pear" "bruised"]])
(prn "is-rollback-only" (jdbc/db-is-rollback-only t-con))
;; is-rollback-only true
;; the following will display the inserted rows:
(jdbc/query t-con ["SELECT * FROM fruit"]
:row-fn println))
(prn)
;; outside the transaction, the following will show the original rows
;; without those two inserted inside the (rolled-back) transaction:
(jdbc/query db-spec ["SELECT * FROM fruit"]
:row-fn println)
</code></pre><h2 id="clojure-identifiers-and-sql-entities">Clojure identifiers and SQL entities</h2><p>As hinted at above, <code>java.jdbc</code> converts SQL entity names in result sets to
keywords in Clojure by making them lowercase, and converts strings and keywords
that specify table and column names (in maps) to SQL entities <em>as-is</em> by
default.</p><p>You can override this behavior by specifying an options map, containing
<code>:identifiers</code>, <code>:keywordize?</code> and/or <code>:qualifier</code>, on any function that
returns or transforms a result set,
and <code>:entities</code>, on any function that transforms Clojure data into SQL.</p><ul><li><code>:identifiers</code> is for converting <code>ResultSet</code> column names to keywords (or strings). It
defaults to <code>clojure.string/lower-case</code>.</li><li><code>:keywordize?</code> controls whether to convert identifiers to keywords (the default) or not.</li><li><code>:qualifier</code> optionally specifies a namespace to qualify keywords with (when
<code>:keywordize?</code> is not falsey).</li><li><code>:entities</code> is for converting Clojure keywords/string to SQL entity names. It
defaults to <code>identity</code> (after calling <code>name</code> on the keyword or string).</li></ul><p>If you want to prevent <code>java.jdbc</code>'s conversion of SQL entity names to lowercase
in a <code>query</code> result, you can specify <code>:identifiers identity</code>:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM mixedTable"]
{:identifiers identity})
;; produces result set with column names exactly as they appear in the DB
</code></pre><p>It you're working with a database that has underscores in column names, you
might want to specify a function that converts those to dashes in Clojure
keywords:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM mixedTable"]
{:identifiers #(.replace % \_ \-)})
</code></pre><p>For several databases, you will often want entities to be quoted in some way
(sometimes referred to as "stropping"). A utility function <code>quoted</code> is provided
that accepts either a single character, a vector pair of characters, or a keyword
as a symbolic name for the type of quoting you want (<code>:ansi</code>, <code>:mysql</code>,
<code>:oracle</code>, <code>:sqlserver</code>), and
returns a function suitable for use with the <code>:entities</code> option.</p><p>For example:</p><pre><code class="clojure">(jdbc/insert! db-spec :fruit
{:name "Apple" :appearance "Round" :cost 99}
{:entities (jdbc/quoted \`)}) ; or (jdbc/quoted :mysql)
</code></pre><p>will execute:</p><pre><code class="clojure">INSERT INTO `fruit` ( `name`, `appearance`, `cost` )
VALUES ( ?, ?, ? )
</code></pre><p>with the parameters <code>"Apple", "Round", "99"</code> whereas:</p><pre><code class="clojure">(jdbc/insert! db-spec :fruit
{:name "Apple" :appearance "Round" :cost 99}
{:entities (jdbc/quoted [\[ \]])}) ; or (jdbc/quoted :sqlserver)
</code></pre><p>will execute:</p><pre><code class="clojure">INSERT INTO [fruit] ( [name], [appearance], [cost] )
VALUES ( ?, ?, ? )
</code></pre><p>with the parameters <code>"Apple", "Round", "99"</code>.</p><h2 id="protocol-extensions-for-transforming-values">Protocol extensions for transforming values</h2><p>By default, <code>java.jdbc</code> leaves it up to Java interop and the JDBC driver library
to perform the appropriate transformations of Clojure values to SQL values and
vice versa. When Clojure values are passed through to the JDBC driver,
<code>java.jdbc</code> uses <code>PreparedStatement/setObject</code> for all values by default. When
Clojure values are read from a <code>ResultSet</code> they are left untransformed, except
that <code>Boolean</code> values are coerced to canonical <code>true</code> / <code>false</code> values in
Clojure (some driver / data type combinations can produce <code>(Boolean. false)</code>
values otherwise, which do not behave like <code>false</code> in all situations).</p><p><code>java.jdbc</code> provides three protocols that you can extend, in order to modify
these behaviors.</p><ul><li><code>ISQLValue</code> / <code>sql-value</code> - simple transformations of Clojure values to SQL
values</li><li><code>ISQLParameter</code> / <code>set-parameter</code> - a more sophisticated transformation of
Clojure values to SQL values that lets you override how the value is stored
in the <code>PreparedStatement</code></li><li><code>IResultSetReadColumn</code> / <code>result-set-read-column</code> - simple transformations of
SQL values to Clojure values when processing a <code>ResultSet</code> object</li></ul><p>If you are using a database that returns certain SQL types as custom Java types
(e.g., PostgreSQL), you can extend <code>IResultSetReadColumn</code> to that type and
define <code>result-set-read-column</code> to perform the necessary conversion to a usable
Clojure data structure. The <code>result-set-read-column</code> function is called with
three arguments:</p><ul><li>The SQL value itself</li><li>The <code>ResultSet</code> metadata object</li><li>The index of the column in the row / metadata</li></ul><p>By default <code>result-set-read-column</code> just returns its first argument (the
<code>Boolean</code> implementation ensure the result is either <code>true</code> or <code>false</code>).</p><p>If you are using a database that requires special treatment of null values,
e.g., TeraData, you can extend <code>ISQLParameter</code> to <code>nil</code> (and <code>Object</code>) and
define <code>set-parameter</code> to use <code>.setNull</code> instead of <code>.setObject</code>. The
<code>set-parameter</code> function is called with three arguments:</p><ul><li>The Clojure value itself</li><li>The <code>PreparedStatement</code> object</li><li>The index of the parameter being set</li></ul><p>By default <code>set-parameter</code> calls <code>sql-value</code> on the Clojure value and then
calls <code>.setObject</code> to store the result of that call into the specified
parameter in the SQL statement.</p><p>For general transformations of Clojure values to SQL values, extending
<code>ISQLValue</code> and defining <code>sql-value</code> may be sufficient. The <code>sql-value</code>
function is called with a single argument: the Clojure value. By default
<code>sql-value</code> just returns its argument.</p>
<div id="prev-next">
<a href="home.html">&laquo; java.jdbc - Getting Started</a>
||
<a href="using_ddl.html">java.jdbc - Using DDL and Metadata &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="home.html">java.jdbc - Getting Started</a></li>
<li><a href="using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,510 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: java.jdbc - Manipulating data with SQL</title>
<meta name="description" content="Contents">
<meta property="og:description" content="Contents">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/using_sql/" />
<meta property="og:title" content="java.jdbc - Manipulating data with SQL" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/using_sql/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>java.jdbc - Manipulating data with SQL</h2>
</div>
<h2 id="contents">Contents</h2><ul><li><a href="../home.html">Overview</a></li><li><a href="../using_sql.html">Using SQL</a></li><li><a href="../using_ddl.html">Using DDL</a></li><li><a href="../reusing_connections.html">Reusing Connections</a></li></ul><h2 id="using-sql">Using SQL</h2><p>Here are some examples of using <code>java.jdbc</code> to manipulate data with SQL.
These examples assume a simple table called <code>fruit</code> (see <a href="https://clojure-doc.org/articles/ecosystem/java_jdbc/using_sql/using_ddl/">Using DDL and
Metadata</a>). These examples all assume the following in your
<code>ns</code> declaration:</p><pre><code class="clojure">(:require [clojure.java.jdbc :as jdbc])
</code></pre><h2 id="reading-and-processing-rows">Reading and processing rows</h2><p><code>java.jdbc</code> provides a simple <code>query</code> function to allow you to read rows from
tables, as well as optionally performing processing on them at the same time.</p><h3 id="reading-rows">Reading rows</h3><p>To obtain a fully realized result set as a sequence of maps, you can use
<code>query</code> with a vector containing the SQL string and any parameters needed by
the SQL:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM fruit"])
;; ({:id 1 :name "Apple" :appearance "red" :cost 59 :grade 87}
;; {:id 2 :name "Banana" :appearance "yellow" :cost 29 :grade 92.2}
;; ...)
(jdbc/query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50])
;; ({:id 2 :name "Banana" :appearance "yellow" :cost 29 :grade 92.2}
;; ...)
</code></pre><p>You can also return the result set as a sequence of vectors. The first vector
will contain the column names, and each subsequent vector will represent a row
of data with values in the same order as the columns.</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:as-arrays? true})
;; ([:id :name :appearance :cost :grade]
;; [2 "Banana" "yellow" 29 92.2]
;; ...)
</code></pre><h3 id="processing-a-result-set-lazily">Processing a result set lazily</h3><p>Since <code>query</code> returns a fully realized result set, it can be difficult to
process very large results. Fortunately, <code>java.jdbc</code> provides a number of ways to process a
large result set lazily while the connection is open, either by passing a function via
the <code>:result-set-fn</code> option or, since release 0.7.0, via <code>reducible-query</code>.</p><p><strong><code>query</code> and <code>:result-set-fn</code></strong></p><p><em>If you are using release 0.7.0 or later, consider using <code>reducible-query</code> instead -- see below.</em></p><p>For <code>:result-set-fn</code>, the function you pass must force
realization of the result to avoid the connection closing while the result set
is still being processed. A <code>reduce</code>-based function is a good choice.</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:result-set-fn (fn [rs]
(reduce (fn [total row-map]
(+ total (:cost row-map)))
0 rs))})
;; produces the total cost of all the cheap fruits: 437
</code></pre><p>Of course, a simple sum like this could be computed directly in SQL instead:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT SUM(cost) FROM fruit WHERE cost &lt; ?" 50]
{:result-set-fn first})
;; {:sum(cost) 437}
</code></pre><p>We know we will only get one row back so passing <code>first</code> to <code>:result-set-fn</code> is
a quick way to get just that row.</p><p>Remember that if you also specify <code>:as-arrays? true</code>, your result set function
will be passed a sequence of vectors in which the first vector contains the
column names and subsequent vectors represent the values in the rows, matching
the order of the column names.</p><p><strong><code>reducible-query</code></strong></p><p>This is the recommended approach since release 0.7.0 but it does come with a few
restrictions:</p><p>You cannot use any of the following options that <code>query</code> accepts:
<code>as-arrays?</code>, <code>:explain</code>, <code>:explain-fn</code>, <code>:result-set-fn</code>, or <code>:row-fn</code>.</p><p>On the other hand, you have access to a much faster way to process result sets:
you can specify <code>:raw? true</code> and no conversion from Java's <code>ResultSet</code> to
Clojure's sequence of hash maps will be performed. In particular, it's as if you
specified <code>:identifiers identity :keywordize? false :qualifier nil</code>, and the
sequence representation of each row is not available. That means no <code>keys</code>,
no <code>vals</code>, no <code>seq</code> calls, just simple key lookup (for convenience, you can
still use keyword lookup for columns, but you can also call <code>get</code> with either a
string or a keyword).</p><p>So how does this work? <code>reducible-query</code> produces a <code>clojure.lang.IReduce</code> which,
when reduced with a function <code>f</code>, performs the query and reduces the <code>ResultSet</code>
using <code>f</code>, opening and closing the connection and/or transaction during the
reduction. For example:</p><pre><code class="clojure">;; our reducing function requires two arguments: we must provide initial val
(reduce (fn [total {:keys [cost]}] (+ total cost))
0
(jdbc/reducible-query db-spec
["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:raw? true}))
;; separating the key selection from the reducing function: we can omit val
(transduce (map :cost)
+ ; can be called with 0, 1, or 2 arguments!
(jdbc/reducible-query db-spec
["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:raw? true}))
;; 437
</code></pre><p>Since <code>reducible-query</code> doesn't actually run the query until you reduce its result,
you can create it once and run it as many times as you want. This will avoid the
overhead of option and parameter validation and handling for repeated reductions,
since those are performed just once in the call to <code>reducible-query</code>. Note that
the SQL parameters are fixed by that call, so this only works for running the
<em>identical</em> query multiple times.</p><p>A reducible companion to <code>result-set-seq</code> also exists, in case you already have
a Java <code>ResultSet</code> and want to create a <code>clojure.lang.IReduce</code>. <code>reducible-result-set</code>
accept almost the same options as <code>result-set-seq</code>: <code>identifiers</code>, <code>keywordize?</code>,
<code>qualifier</code>, and <code>read-columns</code>. It does not accept <code>as-arrays?</code> (for the same
reason that <code>reducible-query</code> does not). Unlike <code>result-set-seq</code>, which produces
a lazy sequence that can be consumed multiple times (with the first pass realizing
it for subsequent passes), <code>reducible-result-set</code> is reducible just once: the
underlying <code>ResultSet</code> is mutable and is consumed during the first reduction!</p><p>It should go without saying that both <code>reducible-query</code> and
<code>reducible-result-set</code> respect <code>reduced</code> / <code>reduced?</code>.</p><p><strong>Additional Options?</strong></p><p>Note: some databases require additional options to be passed in to ensure that
result sets are chunked and lazy. In particular, you may need to pass
<code>:auto-commit?</code>, set appropriately, as an option to whichever function will open your database
connection (<code>with-db-connection</code>, <code>with-db-transaction</code>, or the <code>query</code> / <code>reducible-query</code> itself
if you are passing a bare database spec and expecting <code>query</code> / <code>reducible-query</code> to open and close
the connection directly). You may also need to specify <code>:fetch-size</code>, <code>:result-type</code>,
and possibly other options -- consult your database's documentation for the JDBC
driver you are using.</p><h3 id="processing-each-row-lazily">Processing each row lazily</h3><p>As seen above, using <code>reduce</code>, <code>transduce</code>, etc with a <code>reducible-query</code> allow
you to easily and efficiently process each row as you process the entire
result set, but sometimes you just want a sequence of transformed rows.</p><p>We can process each row with the <code>:row-fn</code> option. Again, like with <code>:result-set-fn</code>,
we pass a function but this time it will be
invoked on each row, as the result set is realized.</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT name FROM fruit WHERE cost &lt; ?" 50]
{:row-fn :name})
;; ("Apple" "Banana" ...)
</code></pre><p>The result is still a fully realized sequence, but each row has been
transformed by the <code>:name</code> function you passed in.</p><p>You can combine this with <code>:result-set-fn</code> to simplify processing of result
sets:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50]
{:row-fn :cost
:result-set-fn (partial reduce +)})
;; produces the total cost of all the cheap fruits
</code></pre><p>or:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT SUM(cost) AS total FROM fruit WHERE cost &lt; ?" 50]
{:row-fn :total
:result-set-fn first})
;; produces the same result, via SQL
</code></pre><p>Here is an example that manipulates rows to add computed columns:</p><pre><code class="clojure">(defn add-tax [row] (assoc row :tax (* 0.08 (:cost row))))
(jdbc/query db-spec ["SELECT * FROM fruit"]
{:row-fn add-tax})
;; produces all the rows with a new :tax column added
</code></pre><p>All of the above can be achieved via <code>reducible-query</code> and the appropriate
reducing function and/or transducer, but with those simple row/result set
functions, the result is often longer / uglier:</p><pre><code class="clojure">(into [] (map :name) (jdbc/reducible-query db-spec ["SELECT name FROM fruit WHERE cost &lt; ?" 50]))
(transduce (map :cost) + (jdbc/reducible-query db-spec ["SELECT * FROM fruit WHERE cost &lt; ?" 50]))
;; :row-fn :total :result-set-fn first left as an exercise for the reader!
(into [] (map add-tax) (jdbc/reducible-query db-spec ["SELECT * FROM fruit"]))
</code></pre><p>If the result set is likely to be large and the reduction can use a <code>:raw? true</code>
result set, <code>reducible-query</code> may be worth the verbosity for the performance gain.</p><h2 id="inserting-data">Inserting data</h2><p>Rows (and partial rows) can be inserted easily using the <code>insert!</code> function.
You can insert a single row, or multiple rows. Depending on how you call
<code>insert!</code>, the insertion will be done either through multiple SQL statements or
through a single, batched SQL statement. That will also determine whether or
not you get back any generated keys.</p><p>If you need a more complex form of insertion, you can use <code>execute!</code> and, if
your database / driver supports it, you can pass <code>:return-keys</code> as an option
to get back the generated keys. As of <code>java.jdbc</code> 0.7.6, this can be a vector
of column names to return (for drivers that support that) or a simple Boolean.</p><h3 id="inserting-a-row">Inserting a row</h3><p>If you want to insert a single row (or partial row) and get back the generated
keys, you can use <code>insert!</code> and specify the columns and their values as a map.
This performs a single insert statement. A single-element sequence containing a
map of the generated keys will be returned.</p><pre><code class="clojure">(jdbc/insert! db-spec :fruit {:name "Pear" :appearance "green" :cost 99})
;; returns a database-specific map as the only element of a sequence, e.g.,
;; ({:generated_key 50}) might be returned for MySQL
</code></pre><p>Not all databases are able to return generated keys from an insert.</p><h3 id="inserting-multiple-rows">Inserting multiple rows</h3><p>There are two ways to insert multiple rows: as a sequence of maps, or as a
sequence of vectors. In the former case, multiple inserts will be performed and
a map of the generated keys will be returned for each insert (as a sequence).
In the latter case, a single, batched insert will be performed and a sequence
of row insert counts will be returned (generally a sequence of ones). The latter
approach is likely to be substantially faster if you are inserting a large number
of rows.</p><p>If you use <code>insert-multi!</code> and specify each row as a map of columns and their values,
then you can specify a mixture of complete and partial rows, and you will get
back the generated keys for each row (assuming the database has that
capability).</p><pre><code class="clojure">(jdbc/insert-multi! db-spec :fruit
[{:name "Pomegranate" :appearance "fresh" :cost 585}
{:name "Kiwifruit" :grade 93}])
;; returns a sequence of database-specific maps, e.g., for MySQL:
;; ({generated_key 51} {generated_key 52})
</code></pre><p>If you use <code>insert-multi!</code> and specify the columns you wish to insert followed by
each row as a vector of column values, then you must specify the same columns
in each row, and you will not get generated keys back, just row counts. If you
wish to insert complete rows, you may omit the column name vector (passing
<code>nil</code> instead) but your rows must match the natural order of columns in your
table so be careful!</p><pre><code class="clojure">(jdbc/insert-multi! db-spec :fruit
nil ; column names not supplied
[[1 "Apple" "red" 59 87]
[2 "Banana" "yellow" 29 92.2]
[3 "Peach" "fuzzy" 139 90.0]
[4 "Orange" "juicy" 89 88.6]])
;; (1 1 1 1) - row counts modified
</code></pre><p>It is generally safer to specify the columns you wish to insert so you can
control the order, and choose to omit certain columns:</p><pre><code class="clojure">(jdbc/insert-multi! db-spec :fruit
[:name :cost]
[["Mango" 722]
["Feijoa" 441]])
;; (1 1) - row counts modified
</code></pre><h2 id="updating-rows">Updating rows</h2><p>If you want to update simple column values in one or more rows based on a
simple SQL predicate, you can use <code>update!</code> with a map, representing the column
values to set, and a SQL predicate with parameters. If you need a more complex
form of update, you can use the <code>execute!</code> function with arbitrary SQL (and
parameters).</p><pre><code class="clojure">;; update fruit set cost = 49 where grade &lt; ?
(jdbc/update! db-spec :fruit
{:cost 49}
["grade &lt; ?" 75])
;; produces a sequence of the number of rows updated, e.g., (2)
</code></pre><p>For a more complex update:</p><pre><code class="clojure">(jdbc/execute! db-spec
["update fruit set cost = ( 2 * grade ) where grade &gt; ?" 50.0])
;; produces a sequence of the number of rows updated, e.g., (3)
</code></pre><h2 id="deleting-rows">Deleting rows</h2><p>If you want to delete any rows from a table that match a simple predicate, the
<code>delete!</code> function can be used.</p><pre><code class="clojure">(jdbc/delete! db-spec :fruit ["grade &lt; ?" 25.0])
;; produces a sequence of the number of rows deleted, e.g., (1)
</code></pre><p>You can also use <code>execute!</code> for deleting rows:</p><pre><code class="clojure">(jdbc/execute! db-spec ["DELETE FROM fruit WHERE grade &lt; ?" 25.0])
;; produces a sequence of the number of rows deleted, e.g., (1)
</code></pre><h2 id="using-transactions">Using transactions</h2><p>You can write multiple operations in a transaction to ensure they are either
all performed, or all rolled back.</p><pre><code class="clojure">(jdbc/with-db-transaction [t-con db-spec]
(jdbc/update! t-con :fruit
{:cost 49}
["grade &lt; ?" 75])
(jdbc/execute! t-con
["update fruit set cost = ( 2 * grade ) where grade &gt; ?" 50.0]))
</code></pre><p>The <code>with-db-transaction</code> macro creates a transaction-aware connection from the
database specification and that should be used in the body of the transaction
code.</p><p>You can specify the transaction isolation level as part of the
<code>with-db-transction</code> binding:</p><pre><code class="clojure">(jdbc/with-db-transaction [t-con db-spec {:isolation :serializable}]
...)
</code></pre><p>Possible values for <code>:isolation</code> are <code>:none</code>, <code>:read-committed</code>,
<code>:read-uncommitted</code>, <code>:repeatable-read</code>, and <code>:serializable</code>. Be aware that not
all databases support all isolation levels. Inside a transaction, you can call
<code>get-isolation-level</code> to return the current level.</p><p>In addition, you can also set the current transaction-aware connection to
rollback, and reset that setting, as well as test whether the connection is
currently set to rollback, using the following functions:</p><pre><code class="clojure">(jdbc/db-set-rollback-only! t-con) ; this transaction will rollback instead of commit
(jdbc/db-unset-rollback-only! t-con) ; this transaction will commit if successful
(jdbc/db-is-rollback-only t-con) ; returns true if transaction is set to rollback
</code></pre><h2 id="updating-or-inserting-rows-conditionally">Updating or Inserting rows conditionally</h2><p><code>java.jdbc</code> does not provide a built-in function for updating existing rows or
inserting a new row (the older API supported this but the logic was too
simplistic to be generally useful). If you need that functionality, it can
sometimes be done like this:</p><pre><code class="clojure">(defn update-or-insert!
"Updates columns or inserts a new row in the specified table"
[db table row where-clause]
(jdbc/with-db-transaction [t-con db]
(let [result (jdbc/update! t-con table row where-clause)]
(if (zero? (first result))
(jdbc/insert! t-con table row)
result))))
(update-or-insert! mysql-db :fruit
{:name "Cactus" :appearance "Spiky" :cost 2000}
["name = ?" "Cactus"])
;; inserts Cactus (assuming none exists)
(update-or-insert! mysql-db :fruit
{:name "Cactus" :appearance "Spiky" :cost 2500}
["name = ?" "Cactus"])
;; updates the Cactus we just inserted
</code></pre><p>If the <code>where-clause</code> does not uniquely identify a single row, this will update
multiple rows which might not be what you want, so be careful!</p><h2 id="exception-handling-and-transaction-rollback">Exception Handling and Transaction Rollback</h2><p>Transactions are rolled back if an exception is thrown, as shown in these
examples.</p><pre><code class="clojure">(jdbc/with-db-transaction [t-con db-spec]
(jdbc/insert-multi! t-con :fruit
[:name :appearance]
[["Grape" "yummy"]
["Pear" "bruised"]])
;; At this point the insert! call is complete, but the transaction is
;; not. The exception will cause it to roll back leaving the database
;; untouched.
(throw (Exception. "sql/test exception")))
</code></pre><p>As noted above, transactions can also be set explicitly to rollback instead of
commit:</p><pre><code class="clojure">(jdbc/with-db-transaction [t-con db-spec]
(prn "is-rollback-only" (jdbc/db-is-rollback-only t-con))
;; is-rollback-only false
(jdbc/db-set-rollback-only! t-con)
;; the following insert will be rolled back when the transaction ends:
(jdbc/insert!-multi t-con :fruit
[:name :appearance]
[["Grape" "yummy"]
["Pear" "bruised"]])
(prn "is-rollback-only" (jdbc/db-is-rollback-only t-con))
;; is-rollback-only true
;; the following will display the inserted rows:
(jdbc/query t-con ["SELECT * FROM fruit"]
:row-fn println))
(prn)
;; outside the transaction, the following will show the original rows
;; without those two inserted inside the (rolled-back) transaction:
(jdbc/query db-spec ["SELECT * FROM fruit"]
:row-fn println)
</code></pre><h2 id="clojure-identifiers-and-sql-entities">Clojure identifiers and SQL entities</h2><p>As hinted at above, <code>java.jdbc</code> converts SQL entity names in result sets to
keywords in Clojure by making them lowercase, and converts strings and keywords
that specify table and column names (in maps) to SQL entities <em>as-is</em> by
default.</p><p>You can override this behavior by specifying an options map, containing
<code>:identifiers</code>, <code>:keywordize?</code> and/or <code>:qualifier</code>, on any function that
returns or transforms a result set,
and <code>:entities</code>, on any function that transforms Clojure data into SQL.</p><ul><li><code>:identifiers</code> is for converting <code>ResultSet</code> column names to keywords (or strings). It
defaults to <code>clojure.string/lower-case</code>.</li><li><code>:keywordize?</code> controls whether to convert identifiers to keywords (the default) or not.</li><li><code>:qualifier</code> optionally specifies a namespace to qualify keywords with (when
<code>:keywordize?</code> is not falsey).</li><li><code>:entities</code> is for converting Clojure keywords/string to SQL entity names. It
defaults to <code>identity</code> (after calling <code>name</code> on the keyword or string).</li></ul><p>If you want to prevent <code>java.jdbc</code>'s conversion of SQL entity names to lowercase
in a <code>query</code> result, you can specify <code>:identifiers identity</code>:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM mixedTable"]
{:identifiers identity})
;; produces result set with column names exactly as they appear in the DB
</code></pre><p>It you're working with a database that has underscores in column names, you
might want to specify a function that converts those to dashes in Clojure
keywords:</p><pre><code class="clojure">(jdbc/query db-spec ["SELECT * FROM mixedTable"]
{:identifiers #(.replace % \_ \-)})
</code></pre><p>For several databases, you will often want entities to be quoted in some way
(sometimes referred to as "stropping"). A utility function <code>quoted</code> is provided
that accepts either a single character, a vector pair of characters, or a keyword
as a symbolic name for the type of quoting you want (<code>:ansi</code>, <code>:mysql</code>,
<code>:oracle</code>, <code>:sqlserver</code>), and
returns a function suitable for use with the <code>:entities</code> option.</p><p>For example:</p><pre><code class="clojure">(jdbc/insert! db-spec :fruit
{:name "Apple" :appearance "Round" :cost 99}
{:entities (jdbc/quoted \`)}) ; or (jdbc/quoted :mysql)
</code></pre><p>will execute:</p><pre><code class="clojure">INSERT INTO `fruit` ( `name`, `appearance`, `cost` )
VALUES ( ?, ?, ? )
</code></pre><p>with the parameters <code>"Apple", "Round", "99"</code> whereas:</p><pre><code class="clojure">(jdbc/insert! db-spec :fruit
{:name "Apple" :appearance "Round" :cost 99}
{:entities (jdbc/quoted [\[ \]])}) ; or (jdbc/quoted :sqlserver)
</code></pre><p>will execute:</p><pre><code class="clojure">INSERT INTO [fruit] ( [name], [appearance], [cost] )
VALUES ( ?, ?, ? )
</code></pre><p>with the parameters <code>"Apple", "Round", "99"</code>.</p><h2 id="protocol-extensions-for-transforming-values">Protocol extensions for transforming values</h2><p>By default, <code>java.jdbc</code> leaves it up to Java interop and the JDBC driver library
to perform the appropriate transformations of Clojure values to SQL values and
vice versa. When Clojure values are passed through to the JDBC driver,
<code>java.jdbc</code> uses <code>PreparedStatement/setObject</code> for all values by default. When
Clojure values are read from a <code>ResultSet</code> they are left untransformed, except
that <code>Boolean</code> values are coerced to canonical <code>true</code> / <code>false</code> values in
Clojure (some driver / data type combinations can produce <code>(Boolean. false)</code>
values otherwise, which do not behave like <code>false</code> in all situations).</p><p><code>java.jdbc</code> provides three protocols that you can extend, in order to modify
these behaviors.</p><ul><li><code>ISQLValue</code> / <code>sql-value</code> - simple transformations of Clojure values to SQL
values</li><li><code>ISQLParameter</code> / <code>set-parameter</code> - a more sophisticated transformation of
Clojure values to SQL values that lets you override how the value is stored
in the <code>PreparedStatement</code></li><li><code>IResultSetReadColumn</code> / <code>result-set-read-column</code> - simple transformations of
SQL values to Clojure values when processing a <code>ResultSet</code> object</li></ul><p>If you are using a database that returns certain SQL types as custom Java types
(e.g., PostgreSQL), you can extend <code>IResultSetReadColumn</code> to that type and
define <code>result-set-read-column</code> to perform the necessary conversion to a usable
Clojure data structure. The <code>result-set-read-column</code> function is called with
three arguments:</p><ul><li>The SQL value itself</li><li>The <code>ResultSet</code> metadata object</li><li>The index of the column in the row / metadata</li></ul><p>By default <code>result-set-read-column</code> just returns its first argument (the
<code>Boolean</code> implementation ensure the result is either <code>true</code> or <code>false</code>).</p><p>If you are using a database that requires special treatment of null values,
e.g., TeraData, you can extend <code>ISQLParameter</code> to <code>nil</code> (and <code>Object</code>) and
define <code>set-parameter</code> to use <code>.setNull</code> instead of <code>.setObject</code>. The
<code>set-parameter</code> function is called with three arguments:</p><ul><li>The Clojure value itself</li><li>The <code>PreparedStatement</code> object</li><li>The index of the parameter being set</li></ul><p>By default <code>set-parameter</code> calls <code>sql-value</code> on the Clojure value and then
calls <code>.setObject</code> to store the result of that call into the specified
parameter in the SQL statement.</p><p>For general transformations of Clojure values to SQL values, extending
<code>ISQLValue</code> and defining <code>sql-value</code> may be sufficient. The <code>sql-value</code>
function is called with a single argument: the Clojure value. By default
<code>sql-value</code> just returns its argument.</p>
<div id="prev-next">
<a href="../home.html">&laquo; java.jdbc - Getting Started</a>
||
<a href="../using_ddl.html">java.jdbc - Using DDL and Metadata &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../../about/index.html">About</a></li>
<li><a href="../../../content/index.html">Table of Contents</a></li>
<li><a href="../../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../community/index.html">Clojure Community</a></li>
<li><a href="../../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../home.html">java.jdbc - Getting Started</a></li>
<li><a href="../using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,343 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Library Development and Distribution</title>
<meta name="description" content="This short guide covers how to create your own typical pure Clojure
library and distribute it to the community via Clojars. It uses
Clojure 1.4 and Leiningen 2.0-previewX, and requires you have git
installed (though very little familiarity with git is required).It&#39;s assumed that you&#39;re already somewhat familiar with Clojure. If
not, see the Getting Started and
Introduction guides.">
<meta property="og:description" content="This short guide covers how to create your own typical pure Clojure
library and distribute it to the community via Clojars. It uses
Clojure 1.4 and Leiningen 2.0-previewX, and requires you have git
installed (though very little familiarity with git is required).It&#39;s assumed that you&#39;re already somewhat familiar with Clojure. If
not, see the Getting Started and
Introduction guides.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/libraries_authoring/" />
<meta property="og:title" content="Library Development and Distribution" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/libraries_authoring/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Library Development and Distribution</h2>
</div>
<p>This short guide covers how to create your own typical pure Clojure
library and distribute it to the community via Clojars. It uses
Clojure 1.4 and Leiningen 2.0-previewX, and requires you have git
installed (though very little familiarity with git is required).</p><p>It's assumed that you're already somewhat familiar with Clojure. If
not, see the <a href="https://clojure-doc.org/articles/ecosystem/libraries_authoring/getting_started/">Getting Started</a> and
<a href="https://clojure-doc.org/articles/ecosystem/libraries_authoring/introduction/">Introduction</a> guides.</p><p>For the purposes of this guide, the library we'll be making is named
"<a href="https://clojars.org/trivial-library-example">trivial-library-example</a>".</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="create-the-project">Create the Project</h2><p>Create your new library project. Names are usually hyphen-separated
lowercase words:</p><pre><code>lein new trivial-library-example
cd trivial-library-example
</code></pre><p>Typical lein usage is <code>lein new &lt;proj-type&gt; &lt;proj-name&gt;</code>, but if you
leave out <code>&lt;proj-type&gt;</code> (as we've done above), lein defaults to
creating a library project for you.</p><p>Our trivial library example project will have a dependency on
<a href="https://clojars.org/org.flatland/useful">flatland's "useful"</a>
library.</p><p>Open up our new project.clj file and make a few changes:</p><ol><li>Add our dependency (<code>[org.flatland/useful "0.9.0"]</code>) to the <code>:dependencies</code> vector.</li><li>Remove "-SNAPSHOT" from version string.</li><li>Write a short description.</li><li>Add a url (if not a homepage, then where it's source is hosted online).</li><li>If you're using a different license, change the value for <code>:license</code>.</li></ol><p>Regarding your choice of license, probably the three most common for
Clojure libs (along with a grossly oversimplified blurb (by this
author) for each) are:</p><ul><li>The <a href="http://directory.fsf.org/wiki/License:EPLv1.0">Eclipse Public License</a> (the default).</li><li>The <a href="http://www.gnu.org/licenses/lgpl.html">LGPL</a> (focused most on
code and additions always being free; includes language addressing
s/w patent concerns). See the <a href="http://www.gnu.org/licenses/license-recommendations.html">FSF's recommendations</a> and their
<a href="http://www.gnu.org/licenses/gpl-howto.html">instructions for use</a>.</li><li>The <a href="http://opensource.org/licenses/MIT">MIT</a> License (focused most on the user's freedom to do what
they want with the code). The FSF calls this the <a href="http://directory.fsf.org/wiki/License:Expat">"Expat"
License</a>.</li></ul><p>Whichever one you choose, update your project.clj (if necessary) to
reflect that choice and save the text of the license as a file named
"LICENSE" or "COPYING" in your project directory.</p><h3 id="a-note-regarding-project-naming">A Note Regarding Project Naming</h3><p>The top line of your project.clj includes something like <code>defproject my-project-name</code>. This means that your project has an <em>artifact-id</em>
of "my-project-name", but it also implies a <em>group-id</em> of
"my-project-name" (group-id = artifact-id).</p><p>The artifact-id is the name of your project. The group-id is used for
namespacing (not the same thing as Clojure namespaces) --- it
identifies to which group/organization a project belongs. Some
examples of group-id's: clojurewerkz, sonian, and org.<em>your-domain</em>.</p><p>You may choose to explicitly use a group-id for your project, if you
like. For example:</p><pre><code>(defproject org.my-domain/my-project-name ...
...)
</code></pre><p>The maintainers of Clojars
<a href="https://github.com/clojars/clojars-web/wiki/Verified-Group-Names">require that new libs be published using verified groups</a>,
such as org.my-domain.</p><p>Read more about groups at
<a href="https://github.com/clojars/clojars-web/wiki/Groups">https://github.com/clojars/clojars-web/wiki/Groups</a>.</p><h2 id="update-the-readme">Update the README</h2><p>Aside from providing a good overview, rationale, and introduction at
the top, you're encouraged to provide some usage examples as well. A
link to the lib's (future) Clojars page (which we'll get to below)
might also be appreciated. Add acknowledgements near the end, if
appropriate. Adjust the copyright and license info at the bottom of
the README as needed.</p><p>Lein provides you with a doc directory and a starter doc/intro.md
file. If you find that you have more to say than will comfortably fit
into the README.md, consider moving content into the doc dir.</p><p>Other goodies you might include in your README.md or doc/*.md files:
tutorial, news, bugs, limitations, alternatives, troubleshooting,
configuration.</p><p>Note that you generally won't add hand-written API documentation into
your readme or other docs, as there are tools for creating that
directly from your source (discussed later).</p><h2 id="create-your-projects-local-git-repository">Create your project's local git repository</h2><p>Before going much further, you probably want to get your project under
version control. Make sure you've got git installed and configured to
know your name and email address (i.e., that at some point you've run
<code>git config --global user.name "Your Name"</code> and <code>git config --global user.email "your-email@somewhere.org"</code>).</p><p>Then, in your project dir, run:</p><pre><code>git init
git add .
git commit -m "The initial commit."
</code></pre><p>At any time after you've made changes and want to inspect them and
commit them to the repository:</p><pre><code>git diff
git add -p
git commit -m "The commit message."
</code></pre><h2 id="write-tests">Write Tests</h2><p>In test/trivial_library_example/core_test.clj, add tests as needed.
An example is provided in there to get you started.</p><h2 id="write-code">Write Code</h2><p>Write code to make your tests pass.</p><p>Remember to add a note at the top of each file indicating copyright
and the license under which the code is distributed.</p><h2 id="run-tests">Run Tests</h2><p>In your project dir:</p><pre><code>lein test
</code></pre><h2 id="commit-any-remaining-changes">Commit any remaining changes</h2><p>Before continuing to the next step, make sure all tests pass and
you've committed all your changes. Check to see the status of your
repo at any time with <code>git status</code> and view changes with <code>git diff</code>.</p><h2 id="create-github-project-and-upload-there">Create github project and Upload there</h2><p>This guide makes use of <a href="https://github.com/">github</a> to host your
project code. If you don't already have a github account, create one,
then log into it. Github provides good documentation on how to <a href="https://help.github.com/articles/set-up-git">get
started</a> and how to
<a href="https://help.github.com/articles/generating-ssh-keys">create an SSH key
pair</a>. If you
haven't already done so, get that set up before continuing.</p><p>Create a new repo there for your project using the icon/button/link
near the top-right.</p><blockquote><p>You will have your local repository, and also a remote duplicate of
it at github.</p></blockquote><p>For the repository name, use the same name as your project directory.
Provide a one-line description and hit "Create repository".</p><p>Once this remote repo has been created, follow the instructions on the
resulting page to "Push an existing repository from the command
line". You'll of course run the <code>git</code> commands from your project
directory:</p><pre><code>git remote add origin git@github.com:uvtc/trivial-library-example.git
git push -u origin master
</code></pre><p>You can now access your online repo. For this tutorial, it's
<a href="https://github.com/uvtc/trivial-library-example">https://github.com/uvtc/trivial-library-example</a>.</p><p>Any changes you commit to your local repository can now be pushed
to the remote one at github:</p><pre><code class="bash"># work work work
git add -p
git commit -m "commit message here"
git push
</code></pre><h2 id="create-a-gpg-key-for-signing-your-releases">Create a GPG key for signing your releases</h2><p>You'll need to create a <a href="http://www.gnupg.org/">gpg</a> key pair, which
will be used by lein to sign any release you make to Clojars. Make
sure you've got gpg installed and kick the tires:</p><pre><code>gpg --list-keys
</code></pre><p>(The first time that command is run, you'll see some notices about
it creating necessary files in your home dir.)</p><p>To create a key pair:</p><pre><code>gpg --gen-key
</code></pre><p>Take the default key type (RSA and RSA), and default key size (2048).
When asked for how long the key should remain valid, choose a year or
two. Give it your real name and email address. When it prompts you for
a comment, you might add one as it can be helpful if you have multiple
keys to keep track of. When prompted for a passphrase, come up with one
that is different from the one used with your ssh key.</p><p>When gpg has completed generating your keypair, you can have it list
what keys it knows about:</p><pre><code>gpg --list-keys
</code></pre><p>We'll use that public key in the next section.</p><h2 id="upload-to-clojars">Upload to Clojars</h2><p>If you don't already have an account at <a href="https://clojars.org/">https://clojars.org/</a>, create
one. After doing so, you'll need to supply your ssh and gpg public
keys to Clojars. For the ssh public key, you can use the same one as
used with github. For the gpg public key, get it by running:</p><pre><code>gpg --export -a &lt;your-key-id&gt;
</code></pre><p>where <code>&lt;your-key-id&gt;</code> is in the output of <code>gpg --list-keys</code> (the
8-character part following the forward slash on the line starting with
"pub"). Copy/paste that output (including the "-----BEGIN PGP PUBLIC
KEY BLOCK-----" and "-----END PGP PUBLIC KEY BLOCK-----") into the
form on your Clojars profile page.</p><p>For more info on working with Clojars, see <a href="https://github.com/clojars/clojars-web/wiki/About">the Clojars
wiki</a>.</p><p>Once your Clojars account is all set up, and it has your public keys,
upload your library to Clojars like so:</p><pre><code>lein deploy clojars
</code></pre><p>You will be asked for your (Clojars) username and password.</p><p>Then you'll be asked for your gpg passphrase. (You won't be asked for
your ssh passphrase because <code>lein deploy clojars</code> uses http rather
than scp --- though Clojars supports both.)</p><p>You should now be able to see your lib's Clojars page: for example,
<a href="https://clojars.org/trivial-library-example">https://clojars.org/trivial-library-example</a>!</p><h2 id="generate-api-docs-optional">Generate API docs (optional)</h2><p>For larger library projects, you may want to automatically generate
API docs (from your docstrings). See
<a href="https://github.com/weavejester/codox">codox</a>. If your library project
is hosted at github, you can use <a href="http://pages.github.com/">github
pages</a> to host the resulting docs.</p><h2 id="announce-optional">Announce (optional)</h2><p>You're welcome to announce the availability of your new library
on the <a href="https://groups.google.com/forum/?fromgroups#!forum/clojure">Clojure Mailing List</a>.</p><h2 id="make-updates-to-your-library">Make Updates to your library</h2><p>Making updates to your lib follows the same pattern as described above:</p><pre><code class="bash"># work test work test
# update version string in project.clj
git add -p
git commit
git push
lein deploy clojars
</code></pre><p>And optionally announce the release on the ML.</p><h3 id="merging-pull-requests">Merging pull-requests</h3><p>Note that if you receive a pull-request at github, you can easily
merge those changes into your project (right there, via the web page
describing the pull-request). Afterwards, update your local repo to
grab those changes as well:</p><pre><code>git pull
</code></pre><h2 id="see-also">See Also</h2><p>For more detailed documentation on various aspects of the procedures
described here, see:</p><ul><li>the <a href="https://github.com/clojars/clojars-web/wiki">Clojars wiki</a></li><li>the
<a href="https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md">Leiningen tutorial</a>
and <a href="https://github.com/technomancy/leiningen/blob/master/doc/DEPLOY.md">deploy
guide</a></li></ul><h2 id="contributors">Contributors</h2><p>John Gabriele <a href="mailto:jmg3000@gmail.com">jmg3000@gmail.com</a> (original author)</p>
<div id="prev-next">
<a href="../libraries_directory/index.html">&laquo; A Directory of Clojure Libraries</a>
||
<a href="../generating_documentation/index.html">Generating Documentation &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,395 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: How to use Maven to build Clojure projects</title>
<meta name="description" content="This guide describes how to use Maven to build projects written in Clojure (or in Clojure,
and other languages, such as Java). Although Leiningen is more popular build tool in the
Clojure community, Maven is also used for some projects, such as Clojure Contrib
libraries, and may be useful when you need to perform some special tasks during build,
that aren&#39;t covered by Leiningen&#39;s plugins, or when you&#39;re integrating Clojure code into
an existing Maven project.What is Maven?">
<meta property="og:description" content="This guide describes how to use Maven to build projects written in Clojure (or in Clojure,
and other languages, such as Java). Although Leiningen is more popular build tool in the
Clojure community, Maven is also used for some projects, such as Clojure Contrib
libraries, and may be useful when you need to perform some special tasks during build,
that aren&#39;t covered by Leiningen&#39;s plugins, or when you&#39;re integrating Clojure code into
an existing Maven project.What is Maven?">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/maven/" />
<meta property="og:title" content="How to use Maven to build Clojure projects" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/maven/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>How to use Maven to build Clojure projects</h2>
</div>
<p>This guide describes how to use Maven to build projects written in Clojure (or in Clojure,
and other languages, such as Java). Although Leiningen is more popular build tool in the
Clojure community, Maven is also used for some projects, such as Clojure Contrib
libraries, and may be useful when you need to perform some special tasks during build,
that aren't covered by Leiningen's plugins, or when you're integrating Clojure code into
an existing Maven project.</p><h2 id="what-is-maven">What is Maven?</h2><p><a href="http://maven.apache.org">Maven</a> is a software project life cycle management tool. It implements dependencies
resolution (with automatic download of missing dependencies from repositories), building &amp;
testing of code, deployment of software, etc. Maven's functionality is extensible with
plugins, so it's possible to use it not only for Java code (primary goal of this tool),
but also for code, written in other languages. You can read more about Maven in
<a href="http://www.sonatype.com/products/maven/documentation/book-defguide">following, freely available book</a>.</p><p>Maven differs from other tools, such as Ant - it describes <em>what</em> we want to do, in
contrast with Ant, that describes <em>how</em> to it. Maven uses declarative style to
describe tasks that we want to execute, and all described tasks are performed by
the corresponding plugins.</p><p>Description of software lifecycle and information about project is stored in <code>pom.xml</code>,
a file that should exist in root directory of the project (and in root directories of
sub-projects, if your project is separated into several modules). Project's information
includes name, identifier and version of the project, and often includes more information:
URL of project's site, information about source code repository (so you can use <code>mvn scm:update</code> goal to update code, for example), etc.</p><h2 id="lifecycle-phases">Lifecycle Phases</h2><p>Project Object Model (POM) defines set of stages for project's lifecycle - they are
called "lifecycle phases". Each phase can include several tasks (goals), that define what
will be performed on given stage. There are several common stages: compilation (<code>compile</code>),
testing (<code>test</code>), creation of package (<code>package</code>), and installation (<code>install</code>). Each of these
phases has dependencies on other phases, that should be executed before its invocation
(compilation should be executed before testing, testing before packaging, etc.).</p><p>Usually developer uses phase's name to start a process. For example, <code>mvn package</code>, or <code>mvn install</code>, etc. But developer can also execute concrete Maven's goal. To do this, he
should specify name of plugin, that implements concrete goal, and task name in given
plugin. For example, <code>mvn clojure:run</code> will start Clojure and execute script, specified in
configuration. We need to mention, that list of goals, that are executed for concrete
lifecycle phase isn't constant - you can change this list by modifying plugin's
configuration.</p><h2 id="maven-and-clojure">Maven and Clojure</h2><p>Clojure's support in Maven is provided by
<a href="https://github.com/talios/clojure-maven-plugin">clojure-maven-plugin</a>, that is available
in Maven's central repository, so it always available. (Besides <code>clojure-maven-plugin</code>,
there is also <a href="https://github.com/pallet/zi">Zi</a> plugin, that was developed as part of
<a href="http://palletops.com/">Pallet</a> project. In contrast to <code>clojure-maven-plugin</code> it's
written in Clojure, and more tightly integrated with Clojure-specific subsystems, such
Marginalia, Ritz, etc.)</p><p>As a base for your projects you can use <code>pom.xml</code> file from
<a href="https://github.com/talios/clojure-maven-example">clojure-maven-example</a> project.</p><p>If you already have <code>pom.xml</code> in your project, then to enable this plugin, you will need to
add following code into <code>&lt;plugins&gt;</code> section of <code>pom.xml</code>:</p><pre><code class="xml"> &lt;plugin&gt;
&lt;groupId&gt;com.theoryinpractise&lt;/groupId&gt;
&lt;artifactId&gt;clojure-maven-plugin&lt;/artifactId&gt;
&lt;version&gt;1.3.10&lt;/version&gt;
&lt;/plugin&gt;
</code></pre><p><em>Attention:</em> version number could be changed as development continues. To find latest
plugin's version number you can use sites <a href="http://mvnrepository.com/artifact/com.theoryinpractise/clojure-maven-plugin">mvnrepository</a> or <a href="http://jarvana.com/jarvana/">Jarvana</a>, that contains
information about packages, registered in Maven's repositories. Besides this, you can
omit plugin version - in this case, Maven will automatically use latest available version
(although this isn't always good idea).</p><p>Declaration of this plugin will give you all implemented functionality - compilation,
testing &amp; running of code, written in Clojure, etc. Although, out of box you'll need to
use complete goals names, such as <code>clojure:compile</code>, <code>clojure:test</code> &amp; <code>clojure:run</code>.</p><p>But you can make your life easier if you'll add these goals into list of goals for
concrete lifecycle phases (<code>compile</code> and <code>test</code>). To do this you need to add section
<code>&lt;executions&gt;</code> into plugin's description, as in following example:</p><pre><code class="xml"> &lt;plugin&gt;
&lt;groupId&gt;com.theoryinpractise&lt;/groupId&gt;
&lt;artifactId&gt;clojure-maven-plugin&lt;/artifactId&gt;
&lt;version&gt;1.3.10&lt;/version&gt;
&lt;executions&gt;
&lt;execution&gt;
&lt;id&gt;compile&lt;/id&gt;
&lt;phase&gt;compile&lt;/phase&gt;
&lt;goals&gt;
&lt;goal&gt;compile&lt;/goal&gt;
&lt;/goals&gt;
&lt;/execution&gt;
&lt;execution&gt;
&lt;id&gt;test&lt;/id&gt;
&lt;phase&gt;test&lt;/phase&gt;
&lt;goals&gt;
&lt;goal&gt;test&lt;/goal&gt;
&lt;/goals&gt;
&lt;/execution&gt;
&lt;/executions&gt;
&lt;/plugin&gt;
</code></pre><p>In this case, source code, written in Clojure will be compiled - this useful if you
implement <code>gen-class</code>, that will be used from Java, or if you don't want to provide source
code for your application. But sometimes it's much better just to pack source code into
jar, and it will compiled during loading of package (this is default behaviour when you're
declaring <code>clojure</code> packaging type) - this allows to avoid binary incompatibility between
different versions of Clojure. To put source code into jar, you need to add following
code into <code>resources</code> section (or change packaging type to <code>clojure</code>):</p><pre><code class="xml"> &lt;resource&gt;
&lt;directory&gt;src/main/clojure&lt;/directory&gt;
&lt;/resource&gt;
</code></pre><p>By default, Clojure's source code is placed in the <code>src/main/clojure</code> directory of the
project's tree, while source code for tests is placed in the <code>src/test/clojure</code> directory.
These default values could be changed in <a href="index.html#configure">plugin's configuration</a>.</p><h3 id="goals-in-the-clojure-maven-plugin">Goals in the Clojure Maven Plugin</h3><p><code>clojure-maven-plugin</code> implements several commands (goals) that could be divided into
following groups:</p><ul><li><p>Goals that work with source code (usually they are linked with corresponding phases of
lifecycle, as it's shown above):</p><ul><li><code>clojure:compile</code>: compiles source code, written in Clojure;</li><li><code>clojure:test</code>: executes tests, written in Clojure.</li><li><code>clojure:test-with-junit</code>: executes tests using JUnit;</li><li><code>clojure:add-source</code>: adds directory with source code to archive <code>...-sources.jar</code>;</li><li><code>clojure:add-testsource</code>: add directory with tests source code into archive
<code>...-testsources.jar</code>.</li></ul></li><li><p>Goals for execution of project's code:</p><ul><li><code>clojure:run</code>: executes script (or scripts) defined by <code>script</code> and/or <code>scripts</code>
configuration directives. This goals is often used to run project with correct
dependencies;</li><li><code>clojure:repl</code>: starts Clojure REPL with all dependencies, specified in project. If
necessary, it also executes script specified in configuration option <code>replScript</code> - for
example, you can put some initialization code into it. If the JLine library was
specified in dependencies, then it will be loaded automatically, making your work in
REPL more comfortable;</li><li><code>clojure:swank</code>: starts Swank server, so you can connect to it from Emacs SLIME. By
default, this server is running on port 4005 (this value could be changed with system
option <code>clojure.swank.port</code>);</li><li><code>clojure:nailgun</code>: starts Nailgun server, so you can connect to it from Vim with
<a href="http://kotka.de/projects/clojure/vimclojure.html">vimclojure</a>. By default, this server is running on port 2113 (this value could be
changed with system option <code>clojure.nailgun.port</code>).</li></ul></li><li><p>Auxiliary tasks:</p><ul><li><code>clojure:marginalia</code>: generates documentation using <a href="http://fogus.github.com/marginalia/">Marginalia</a>;</li><li><code>clojure:autodoc</code>: generates documentation using <a href="http://tomfaulhaber.github.com/autodoc/">autodoc</a>;</li><li><code>clojure:gendoc</code>: generates documentation using gendoc.</li></ul></li></ul><h3 id="clojure-related-repositories">Clojure-related repositories</h3><p>There are several Clojure-related repositories. All Clojure versions (stable &amp;
development) are published at <a href="http://dev.clojure.org/display/doc/Maven+Settings+and+Repositories">Sonatype repository</a> that is periodically synchronized with
Maven Central. <a href="http://clojars.org">Clojars</a> is repository that is used by Clojure community to publish their
projects.</p><p>To use repository you need to add following code into <code>repositories</code> section in <code>pom.xml</code>:</p><pre><code class="xml"> &lt;repository&gt;
&lt;id&gt;clojars&lt;/id&gt;
&lt;url&gt;http://clojars.org/repo/&lt;/url&gt;
&lt;/repository&gt;
</code></pre><h3 id="dependencies-management">Dependencies Management</h3><p>Maven automatically downloads the all necessary dependencies from the default repository (known as
Maven Central), and
repositories, specified by user (as shown above). Downloaded packages are stored in
user's home directory and could be used by other projects without additional downloading.
Each package is uniquely identified by combination of three parameters - group's name
(the <code>groupId</code> tag), artifact's name (the <code>artifactId</code> tag), and version (the <code>version</code> tag).</p><p>To use Clojure in your project you need at least specify dependency on language itself.
Right now, the stable version of Clojure is 1.4.0. To declare this dependency, add
following code into <code>dependencies</code> section of <code>pom.xml</code> file:</p><pre><code class="xml"> &lt;dependency&gt;
&lt;groupId&gt;org.clojure&lt;/groupId&gt;
&lt;artifactId&gt;clojure&lt;/artifactId&gt;
&lt;version&gt;1.4.0&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><p>If you want to use the latest version of the language, then you need to add corresponding
repository (snapshots) and use version number like <code>1.5.0-master-SNAPSHOT</code> instead of version
<code>1.4.0</code>.</p><p>To perform some tasks, implemented by <code>clojure-maven-plugin</code>, you need to specify additional
dependencies.</p><p>If you will use <code>clojure:swank</code> goal, then you need to specify dependency on <code>swank-clojure</code> package:</p><pre><code class="xml"> &lt;dependency&gt;
&lt;groupId&gt;swank-clojure&lt;/groupId&gt;
&lt;artifactId&gt;swank-clojure&lt;/artifactId&gt;
&lt;version&gt;1.4.2&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><p>If you will use <code>clojure:nailgun</code> task, then you need to download distribution from
<a href="http://kotka.de/projects/clojure/vimclojure.html">vimclojure</a>'s site, build it, as described in documentation, and install into local
Maven repository. And after this, you need to add following dependency on
<code>vimclojure</code> with following code:</p><pre><code class="xml">&lt;dependency&gt;
&lt;groupId&gt;de.kotka&lt;/groupId&gt;
&lt;artifactId&gt;vimclojure&lt;/artifactId&gt;
&lt;version&gt;X.Y.Z&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><p>The JLine library isn't required, but it could be useful if you plan to use the REPL -
this library implements support for command history and other nice things. Presence of this library is detected
automatically when <code>mvn clojure:repl</code> goal is executed. You can add dependency for this
library with following code:</p><pre><code class="xml"> &lt;dependency&gt;
&lt;groupId&gt;jline&lt;/groupId&gt;
&lt;artifactId&gt;jline&lt;/artifactId&gt;
&lt;version&gt;0.9.94&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><h3 id="plugins-configuration">Plugin's Configuration</h3><p>Developer can change plugin's configuration options, such as location of source code,
scripts names, etc. To change some parameter, you need to add its new value into
<code>configuration</code> section of the plugin's description. For example, you can specify name of
the script, that will be executed during testing, using following code:</p><pre><code class="xml">&lt;plugin&gt;
&lt;groupId&gt;com.theoryinpractise&lt;/groupId&gt;
&lt;artifactId&gt;clojure-maven-plugin&lt;/artifactId&gt;
&lt;version&gt;1.3.10&lt;/version&gt;
&lt;configuration&gt;
&lt;testScript&gt;src/test/clojure/test.clj&lt;/testScript&gt;
&lt;/configuration&gt;
.....
&lt;/plugin&gt;
</code></pre><p>Following options are used to specify options related to source code &amp; compilation:</p><ul><li><code>sourceDirectories</code> - this option defines list of directories (each of them should be
wrapped into <code>sourceDirectory</code> tag) that contains source code written in Clojure, and that
will be packed into resulting jar (and compiled, if corresponding option is specified);</li><li><code>testSourceDirectories</code> - defines list of directories (each of them should be wrapped into
<code>testSourceDirectory</code> tag) with tests, written in Clojure;</li><li><code>warnOnReflection</code> - option that enables (<code>true</code>) or disables (<code>false</code>) warnings about
reflection during compilation of source code.</li></ul><p>Besides this, you can control which namespaces will be compiled and/or for which
namespaces testing of source code will be performed. To do this, you need to add
<code>namespaces</code> tag into configuration and list corresponding namespaces inside it (each of
item should be wrapped into <code>namespace</code> tag). You can use regular expressions to specify
all necessary namespaces, and you can also use <code>!</code> to exclude namespaces from this list. In
addition to this option, you can use other two: <code>compileDeclaredNamespaceOnly</code> and
<code>testDeclaredNamespaceOnly</code> (with values <code>true</code> or <code>false</code>) - they control, will be these
namespace limitations applied during compilation and/or testing.</p><p>There are also several options that are used to specify parameters for execution of your
code and/or tests:</p><ul><li><code>script</code> and <code>scripts</code> - defines one (<code>script</code> tag) or several (<code>scripts</code> tag with nested <code>script</code>
tags) names of scripts with code, that will executed when you'll execute the
<code>clojure:run</code> task;</li><li><code>testScript</code>: defines name of script that will executed when you'll execute <code>clojure:test</code>
task. If there was no value specified in plugin's configuration, then plugin will
automatically generate run script for all tests, that was found in project;</li><li><code>replScript</code> - defines name of script, that will executed if you'll execute <code>clojure:repl</code> task
(it's also used by <code>clojure:swank</code> and <code>clojure:nailgun</code> tasks). This code will executed
before entering into REPL, so you can use it to specify initialization code for your
working environment;</li><li><code>runWithTests</code> - enables (<code>true</code>) or disables (<code>false</code>) executions of tests if you run REPL or
your code via Maven. You can also change this value by using Maven's command-line
option. For example, using following command <code>mvn clojure:repl -Dclojure.runwith.test=false</code>;</li><li><code>clojureOptions</code> - using this option you can specify command-line options that will be
passed to <code>java</code> process on every invocation.</li></ul><h2 id="wrapping-up">Wrapping Up</h2><p>I think, that this article provides enough information for you to start use Maven together
with Clojure. If you have Clojure-only project, and you don't plan to use all power of
Maven, then may be you can look to the <a href="https://clojure-doc.org/articles/ecosystem/maven/leiningen.md">Leiningen</a> - this tool was created to build
projects, written mostly in Clojure. Another interesting project is <a href="http://polyglot.sonatype.org/">Polyglot Maven</a>, the
main goal of it is creation of special DSL (Domain Specificl Language) using different
languages (Clojure, Scala, Groovy) for description of Maven's configurations (for Clojure
this language is almost the same as language implemented in Leiningen).</p><p>Other examples of using Maven with Clojure you can find in different projects: <a href="https://github.com/liebke/incanter/tree/1.0.x">Incanter</a>
(as example of project, consisting from several modules), <a href="https://github.com/relevance/labrepl">labrepl</a> and
the <a href="https://github.com/talios/clojure-maven-example">clojure-maven-example</a>.</p><h2 id="where-to-learn-more">Where To Learn More</h2><p>More information on Clojure and Maven you can also find in
following blog posts:</p><ul><li><a href="http://muckandbrass.com/web/display/~cemerick/2010/03/25/Why+using+Maven+for+Clojure+builds+is+a+no-brainer">Why using Maven for Clojure builds is a no-brainer</a> (including video, that shows how to work with the <code>clojure-maven-plugin</code>)</li><li><a href="http://pupeno.com/blog/how-to-create-a-clojure-application/">How to create a Clojure application</a></li><li><a href="http://stuartsierra.com/2009/09/03/mavens-not-so-bad">Mavens Not So Bad</a>.</li></ul><h2 id="contributors">Contributors</h2><p><a href="http://alexott.net/en/index.html">Alex Ott</a>, 2012 (original author)</p>
<div id="prev-next">
<a href="../web_development/index.html">&laquo; Web Development (Overview)</a>
||
<a href="../community/index.html">Clojure Community &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,209 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Running a Clojure User Group</title>
<meta name="description" content="About this tutorialThis guide covers:">
<meta property="og:description" content="About this tutorialThis guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/running_cljug/" />
<meta property="og:title" content="Running a Clojure User Group" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/running_cljug/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Running a Clojure User Group</h2>
</div>
<h2 id="about-this-tutorial">About this tutorial</h2><p>This guide covers:</p><ul><li>Starting a user group</li><li>Tips for keeping it going</li><li>Meeting ideas</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="starting-a-user-group">Starting a user group</h2><p>Learning Clojure is easier (and more fun) if you can do it with others. Some of the essentials you will need to work out before your first meeting:</p><h3 id="meeting-time">Meeting time</h3><p>If you have a handful of interested parties, it's best to run a quick poll with some options for day of the week to find the most promising candidates and then unilaterally pick one. If evenings are challenging, consider a breakfast or lunch get together!</p><h3 id="location">Location</h3><p>Location can sometimes be the hardest part of creating a new group. Some ideas:</p><ul><li>Ask a software, consulting, or recruiting company in the area. Hosting a group is a great way for potential hires to learn about a company.</li><li>Many libraries and public spaces can be reserved for meetings.</li><li>A get together at a local bar or coffee shop can be enough at the beginning.</li></ul><h3 id="meeting-format">Meeting format</h3><p>Most Clojure user groups follow one of three models:</p><ul><li>Talk with a speaker</li><li>Coding exercises (dojo, swarm coding, pairing, etc)</li><li>Informal chat</li></ul><h3 id="speakers">Speakers</h3><p>If you have trouble getting speakers, try assigning a topic (a Clojure feature, library, etc) to someone to present at the next meeting.</p><h3 id="meeting-organization">Meeting organization</h3><p>By far the two most popular ways to organize your group are <a href="http://meetup.com">Meetup</a> (use discount code "clojure" for 50% off!) or Google group mailing lists.
Also consider creating a GitHub organization where attendees can find each others' code repos.</p><h2 id="keeping-it-going">Keeping it going</h2><p>Once you get the first meeting or two under your belt, you have to worry about how to keep it going. Consistency is one of the most important things in getting a group going - as much as possible try to stick to a stable meeting date and location.</p><p>When the group is young youll need to spend some effort marketing to help it grow — this is one of the reasons that Meetup.com shines. If there are local calendars, get your group listed.</p><p>Create a web site! Domain names and hosting are cheap — its totally worth creating a blog site dedicated to the group on your own domain name.</p><p>Create a Twitter account for the group and post info related to the group as well as specific to your topic. Ask all attendees to post about meetings on Twitter and blogs. Record your talks and put them on the net.</p><p>Consider using a private mailing list for those that attend the meetings. This is a somewhat unusual choice these days but having the limited membership means that you generally know the people that write on the mailing list and having it closed means that people can be a bit more free in asking newbie questions. Both factors contribute to a closer-knit feeling of local community.</p><p>Once you get to a certain size (or if you are fortunate to have good companies involved), you can find sponsors that provide food for your group.</p><h2 id="meeting-ideas">Meeting ideas</h2><p>Looking for meeting ideas? Here's some ideas....</p><ul><li>Work through through the <a href="https://github.com/functional-koans/clojure-koans">Clojure Koans</a></li><li>Work through problems from <a href="http://www.4clojure.com/">4Clojure</a></li><li>Run a session on getting set up on Emacs with Clojure (or Vim, or ...)</li><li>Work through <a href="http://projecteuler.net/">Project Euler</a> problems</li><li>Work through a <a href="http://codekata.pragprog.com/">Code Kata</a></li><li>Implement a game (Tic-Tac-Toe, Rock-Paper-Scissors, Checkers, Othello, etc)</li><li>Build a web site for your group in Clojure and deploy it to Heroku!</li><li>Review and expand <a href="https://clojure-doc.github.io">Clojure documentation</a> guides</li><li>Look through the <a href="http://dev.clojure.org/jira/secure/Dashboard.jspa">Clojure JIRA</a> for bugs to work on</li></ul><p>And some tips:</p><ul><li><a href="http://otfrom.wordpress.com/2012/07/04/how-to-run-a-london-clojure-dojo-in-20ish-easy-steps/">Running a Clojure dojo</a></li><li><a href="http://www.infoq.com/presentations/Swarm-Coding">Swarm coding how-to</a></li></ul><h2 id="troubleshooting">Troubleshooting</h2><h3 id="i-cant-find-enough-people-for-a-group">I can't find enough people for a group</h3><p>You might think of broadening the scope to pull in people that are interested in something similar but not exactly the same. If you can't find enough
people for a Clojure user group, maybe a functional programming group would capture other people interested in Erlang, Scala, Haskell, F#, etc.</p><h2 id="contributors">Contributors</h2><p>Alex Miller <a href="mailto:alex@puredanger.com">alex@puredanger.com</a> (original author)</p>
<div id="prev-next">
<a href="../user_groups/index.html">&laquo; Clojure User Groups</a>
||
<a href="../books/index.html">Books about Clojure and ClojureScript &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,239 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Web Development (Overview)</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/web_development/" />
<meta property="og:title" content="Web Development (Overview)" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/web_development/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Web Development (Overview)</h2>
</div>
<p>This guide covers:</p><ul><li>popular tools and libraries for web development</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.4.</p><h2 id="some-options">Some Options</h2><p>Below are some of the various options available for web development
with Clojure, listed roughly by size.</p><h3 id="ring-and-compojure">Ring and Compojure</h3><p>Perhaps the simplest and most minimal setup is to use only Ring and
Compojure. To get started, see the <a href="../../tutorials/basic_web_development/index.html">basic web development
tutorial</a>.</p><h3 id="lib-noir">lib-noir</h3><p>In addition to Ring and Compojure, you might also make use of
<a href="https://github.com/noir-clojure/lib-noir">lib-noir</a>.</p><h3 id="luminus">Luminus</h3><p><a href="http://www.luminusweb.net/">Luminus</a> is <a href="https://github.com/yogthos/luminus-template">a lein
template</a> for creating
batteries-included web applications. It makes use of Ring, Compojure,
lib-noir, and optionally (as described in its documentation) other
libraries.</p><h2 id="templating-libraries">Templating Libraries</h2><p>Clojure has many options for building HTML.</p><h3 id="hiccup">Hiccup</h3><p><a href="https://github.com/weavejester/hiccup">Hiccup</a> represents HTML as
Clojure data structures, allowing you to create and manipulate your
HTML easily.</p><p><a href="https://github.com/davidsantiago/tinsel">Tinsel</a> is a library that
extends Hiccup with selectors and transformers, so that you can write
a template separate from the insertion of your data into the template.</p><h3 id="mustache">Mustache</h3><p><a href="https://github.com/fhd/clostache">Clostache</a> implements the
<a href="http://mustache.github.com/">Mustache</a> templating language for
Clojure.</p><p><a href="https://github.com/davidsantiago/stencil">Stencil</a> is another
implementation of Mustache.</p><h3 id="fleet">Fleet</h3><p><a href="https://github.com/Flamefork/fleet">Fleet</a> embeds Clojure inside HTML
templates, much like Java's JSPs, or Ruby's ERb.</p><h3 id="clabango">Clabango</h3><p><a href="https://github.com/danlarkin/clabango">Clabango</a> is modeled after the
<a href="https://docs.djangoproject.com/en/1.4/topics/templates/">Django templating system</a>. It
embeds special tags and filters inside HTML templates to insert and
manipulate data.</p><h3 id="selmer">Selmer</h3><p><a href="https://github.com/yogthos/Selmer">Selmer</a> is also modeled after the Django
templating system with a primary goal of performance.</p><h3 id="enlive-and-laser">Enlive and Laser</h3><p><a href="https://github.com/cgrand/enlive">Enlive</a> and
<a href="https://github.com/Raynes/laser">Laser</a> are similar libraries. They
both manipulate plain HTML, and can be used for screen scraping as
well as templating. They work with HTML templates with no special
embedded tags or code. They use selector functions to find pieces of
HTML and transformation function to change the HTML into the way you
want.</p><p>See the
<a href="https://github.com/Raynes/laser/blob/master/docs/guide.md">Laser guide</a>
to see if this style of templating works for you. It is powerful, but
different from most other languages' templating libraries.</p><h2 id="see-also">See Also</h2><ul><li><p>the <a href="../libraries_directory/index.html#web_development">web development section of the library
directory</a>.</p></li><li><p><a href="http://brehaut.net/blog/2012/clojure_web_and_the_crud_stack">The Clojure Web Stack and the CRUD Stack</a></p></li><li><p><a href="http://brehaut.net/blog/2011/ring_introduction">A Brief Overview of the Clojure Web Stack</a></p></li></ul><h2 id="contributors">Contributors</h2><ul><li>John Gabriele</li><li>Clinton Dreisbach</li></ul>
<div id="prev-next">
<a href="../data_processing/index.html">&laquo; Data Processing (Help Wanted)</a>
||
<a href="../maven/index.html">How to use Maven to build Clojure projects &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="index.html">Web Development (Overview)</a></li>
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../community/index.html">Clojure Community</a></li>
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,648 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Collections and Sequences in Clojure</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/collections_and_sequences/" />
<meta property="og:title" content="Collections and Sequences in Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/collections_and_sequences/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Collections and Sequences in Clojure</h2>
</div>
<p>This guide covers:</p><ul><li>Collections in Clojure</li><li>Sequences in Clojure</li><li>Core collection types</li><li>Key operations on collections and sequences</li><li>Other topics related to collections and sequences</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5.</p><h2 id="overview">Overview</h2><p>Clojure provides a number of powerful abstractions including <em>collections</em> and <em>sequences</em>.
When working with Clojure,
many operations are expressed as a series of operations on collections or sequences.</p><p>Most of Clojure's core library treats collections and sequences the same way, although
sometimes a distinction has to be made (e.g. with lazy infinite sequences).</p><p><code>clojure.core</code> provides many fundamental operations on collections, such as: <code>map</code>, <code>filter</code>,
<code>remove</code>, <code>take</code>, and <code>drop</code>. Basic operations on collections and sequences are combined
to implement more complex operations.</p><h3 id="clojure-collections-are-immutable-persistent">Clojure Collections are Immutable (Persistent)</h3><p>Clojure collections are <em>immutable</em> (<em>persistent</em>). The term "persistent data structures" has
nothing to do with durably storing them on disk. What it means is that collections are
mutated (updated) by producing new collections. To quote Wikipedia:</p><blockquote><p>In computing, a persistent data structure is a data structure that always preserves
the previous version of itself when it is modified. Such data structures are effectively
immutable, as their operations do not (visibly) update the structure in-place, but instead
always yield a new updated structure.</p></blockquote><p>Clojure's persistent data structures are implemented as trees and <a href="https://en.wikipedia.org/wiki/Hash_array_mapped_trie"><em>tries</em></a> and
have O(log<sub>32</sub> <em>n</em>) access complexity where <em>n</em> is the number of elements.</p><h2 id="the-collection-abstraction">The Collection Abstraction</h2><p>Clojure has a collection abstraction with several key operations supported for
all collection implementations. They are</p><ul><li><code>=</code>: checks value equality of a collection compared to other collections</li><li><code>count</code>: returns number of elements in a collection</li><li><code>conj</code>: adds an item to a collection in the most efficient way</li><li><code>empty</code>: returns an empty collection of the same type as the argument</li><li><code>seq</code>: gets a sequence of a collection</li></ul><p>These functions work on all core Clojure collection types.</p><h2 id="core-collection-types">Core Collection Types</h2><p>Clojure has several core collection types:</p><ul><li>Maps (called hashes or dictionaries in some other languages)</li><li>Vectors</li><li>Lists</li><li>Sets</li></ul><h3 id="maps">Maps</h3><p>Maps associate keys with values. Boths keys and values can be of any type, but
keys must be comparable. There are several implementations of maps with
different guarantees about ordering. Hash maps are typically instantiated with literals:</p><pre><code class="clojure">{:language "Clojure" :creator "Rich Hickey"}
</code></pre><p>Commas can be used in map literals (Clojure compiler treats the comma as whitespace):</p><pre><code class="clojure">{:language "Clojure", :creator "Rich Hickey"}
</code></pre><p><code>clojure.core/sorted-map</code> and <code>clojure.core/array-map</code> produce ordered maps:</p><pre><code class="klipse-clojure nohighlight">(sorted-map :language "Clojure" :creator "Rich Hickey")
;; ⇒ {:creator "Rich Hickey", :language "Clojure"}
</code></pre><pre><code class="klipse-clojure nohighlight">(array-map :language "Clojure" :creator "Rich Hickey")
;; ⇒ {:creator "Rich Hickey", :language "Clojure"}
</code></pre><p>Unsurprisingly, map literals must contain an even number of forms (as many keys as values). Otherwise
the code will not compile:</p><pre><code class="klipse-clojure nohighlight">{:language "Clojure" :creator}
</code></pre><p>In general, the only major difference between Clojure maps and maps/hashes/dictionaries in some other languages
is that Clojure maps are <em>immutable</em>. When a Clojure map is modified, the result is a new map that internally
has structural sharing (for efficiency reasons) but semantically is a separate immutable value.</p><h4 id="maps-as-functions">Maps As Functions</h4><p>Maps in Clojure can be used as functions on their keys. See the <a href="../functions/index.html#maps_as_functions">Functions guide</a>
for more information.</p><h4 id="keywords-as-functions">Keywords As Functions</h4><p>Keywords in Clojure can be used as functions on maps. See the <a href="../functions/index.html#keywords_as_functions">Functions guide</a>
for more information.</p><h3 id="vectors">Vectors</h3><p>Vectors are collections that offer efficient random access (by index). They are typically instantiated with
literals:</p><pre><code class="clojure">[1 2 3 4]
["clojure" "scala" "erlang" "f#" "haskell" "ocaml"]
</code></pre><p>Commas can be used to separate vector elements (Clojure compiler treats
the comma as whitespace):</p><pre><code class="clojure">["clojure", "scala", "erlang", "f#", "haskell", "ocaml"]
</code></pre><p>Unlike lists, vectors are not used for function invocation. They are, however, used to make certain
forms (e.g. the list of locals in <code>let</code> or parameters in <code>defn</code>) stand out visually. This was
an intentional decision in Clojure design.</p><h3 id="lists">Lists</h3><p>Lists in Clojure are singly linked lists. Access or modifications of list head is efficient, random access
is not.</p><p>Lists in Clojure are special because they represent code forms, from function calls to macro calls to special forms.
Code is data in Clojure and it is represented primarily as lists:</p><pre><code class="klipse-clojure nohighlight">(empty? [])
</code></pre><p>First item on the list is said to be in the <em>calling position</em>.</p><p>When used as "just" data structures, lists are typically instantiated with literals with quoting:</p><pre><code class="klipse-clojure nohighlight">'(1 2 3 4)
</code></pre><pre><code class="klipse-clojure nohighlight">'("clojure" "scala" "erlang" "f#" "haskell" "ocaml")
</code></pre><p>Or you can explicitly use the <code>list</code> form:</p><pre><code class="klipse-clojure nohighlight">(list 1 2 3 4)
;; ⇒ (1 2 3 4)
</code></pre><p>Commas can be used to separate list elements (Clojure compiler treats
the comma as whitespace):</p><pre><code class="klipse-clojure nohighlight">'("clojure", "scala", "erlang", "f#", "haskell", "ocaml")
</code></pre><h4 id="lists-and-metaprogramming-in-clojure">Lists and Metaprogramming in Clojure</h4><p>Metaprogramming in Clojure (and other Lisp dialects) is different from metaprogramming in, say, Ruby, because
in Ruby metaprogramming is <em>primarily</em> about producing strings while in Clojure it is about producing
<em>data structures</em> (mostly <em>lists</em>). For sophisticated DSLs, producing data structures directly lets
developers avoid a lot of incidental complexity that string generation brings along.</p><p>This topic is covered in detail in the <a href="../macros/index.html">Macros and Metaprogramming</a>.</p><h3 id="sets">Sets</h3><p>Sets are collections that offer efficient membership check operation and only allow each element to appear in the collection
once. They are typically instantiated with literals:</p><pre><code class="klipse-clojure nohighlight">#{1 2 3 4}
</code></pre><pre><code class="klipse-clojure nohighlight">#{"clojure" "scala" "erlang" "f#" "haskell" "ocaml"}
</code></pre><p>Commas can be used to separate set elements (Clojure compiler treats the as whitespace):</p><pre><code class="klipse-clojure nohighlight">#{"clojure", "scala", "erlang", "f#", "haskell", "ocaml"}
</code></pre><h4 id="sets-as-functions">Sets As Functions</h4><p>Sets in Clojure can be used as functions on their elements. See the <a href="../functions/index.html#sets_as_functions">Functions guide</a>
for more information.</p><h4 id="set-membership-checks">Set Membership Checks</h4><p>The most common way of checking if an element is in a set is by using set as a function:</p><pre><code class="klipse-clojure nohighlight">(#{1 2 3 4} 1)
;; ⇒ 1
</code></pre><pre><code class="klipse-clojure nohighlight">(#{1 2 3 4} 10)
;; ⇒ nil
</code></pre><pre><code class="klipse-clojure nohighlight">(if (#{1 2 3 4} 1)
:hit
:miss)
;; ⇒ :hit
</code></pre><h2 id="sequences">Sequences</h2><p>The sequence abstraction represents a sequential view of a collection or collection-like
entity (computation result).</p><p><code>clojure.core/seq</code> is a function that produces a sequence over the given argument.
Data types that <code>clojure.core/seq</code> can produce a sequence over are called <em>seqable</em>:</p><ul><li>Clojure collections</li><li>Java maps</li><li>All iterable types (types that implement <code>java.util.Iterable</code>)</li><li>Java collections (<code>java.util.Set</code>, <code>java.util.List</code>, etc)</li><li>Java arrays</li><li>All types that implement <code>java.lang.CharSequence</code> interface, including Java strings</li><li>All types that implement <code>clojure.lang.Seqable</code> interface</li><li>nil</li></ul><p>The sequence abstraction supports several operations:</p><ul><li><code>first</code></li><li><code>rest</code></li><li><code>next</code></li></ul><p>and there are two ways to produce a sequence:</p><ul><li><code>seq</code> produces a sequence over its argument (often a collection)</li><li><code>lazy-seq</code> creates a <em>lazy sequence</em> (that is produced by performing computation)</li></ul><h3 id="seq-cons-list">seq, cons, list*</h3><p><code>clojure.core/seq</code> takes a single argument and returns a sequential view over it:</p><pre><code class="klipse-clojure nohighlight">(seq [1 2 3])
;; ⇒ (1 2 3)
</code></pre><p>When given an empty collection or sequence, <code>clojure.core/seq</code> returns nil:</p><pre><code class="klipse-clojure nohighlight">(seq [])
;; ⇒ nil
</code></pre><p>this is commonly used in the following pattern:</p><pre><code class="klipse-clojure nohighlight">(if (seq xs)
(comment "Do something with this sequence")
(comment "Do something else"))
</code></pre><p>Another function that constructs sequences is <code>clojure.core/cons</code>. It prepends values to the head of
the given sequence:</p><pre><code class="klipse-clojure nohighlight">(cons 0 (range 1 3))
;; ⇒ (0 1 2)
</code></pre><p><code>clojure.core/list*</code> does the same for a number of values:</p><pre><code class="klipse-clojure nohighlight">(list* 0 1 (range 2 5))
;; ⇒ (0 1 2 3 4)
</code></pre><p><code>clojure.core/cons</code> and <code>clojure.core/list*</code> are primarily used to produce lazy sequences and in metaprogramming (when writing
macros). As far as metaprogramming goes, sequences and lists are the same and it is common to
add items in the beginning of the list (into the <em>calling position</em>).</p><p>Note that <code>clojure.core/cons</code> does not create cons cells and lists in Clojure are not implemented
as linked cons cells (like in many other dialects of Lisp).</p><h3 id="first-rest-next">first, rest, next</h3><p><code>clojure.core/first</code> returns the first item in the sequence. <code>clojure.core/next</code> and <code>clojure.core/rest</code>
return the rest:</p><pre><code class="klipse-clojure nohighlight">(first (seq [1 2 3 4 5 6]))
;; ⇒ 1
(rest (seq [1 2 3 4 5 6]))
;; ⇒ (2 3 4 5 6)
</code></pre><p>the difference between them is what they return on a single element sequence:</p><pre><code class="klipse-clojure nohighlight">(rest (seq [:one]))
;; ⇒ ()
</code></pre><pre><code class="klipse-clojure nohighlight">(next (seq [:one]))
;; ⇒ nil
</code></pre><h3 id="lazy-sequences-in-clojure">Lazy Sequences in Clojure</h3><p><em>Lazy sequences</em> are produced by performing computation or I/O. They can be infinite
or not have exact length (e.g. a sequence of all powers of 2 or an audio stream).</p><p>Lazy sequences is an broad topic and covered in the <a href="../laziness/index.html">Laziness</a> guide.</p><h2 id="key-operations-on-collections-and-sequences">Key Operations on Collections and Sequences</h2><p>Below is an overview of <code>clojure.core</code> functions that work on collections and sequences. Most of them
work the same way for all types of collections, however, there are exception to this rule. For example,
functions like <code>clojure.core/assoc</code>, <code>clojure.core/dissoc</code> and <code>clojure.core/get-in</code> only really
make sense in the context of maps and other associative data structures (for example, records).</p><p><code>clojure.core/conj</code> adds elements to a collection in the most efficient manner, which depends on
collection implementation details and won't be the same for vectors and lists.</p><p>In general, Clojure design emphasizes that operations on collections and sequences should be uniform and
follow the principle of least surprise. In real world projects, however, the difference between
algorithmic complexity and other runtime characteristics of various collection types often cannot
be ignored. Keep this in mind.</p><p>You can find more information in the <a href="../core_overview/index.html">clojure.core Overview</a> and <a href="http://clojure.org/cheatsheet">Clojure cheatsheet</a>.</p><h3 id="count">count</h3><p>Returns a count of the number of items in a collection. An argument of nil returns 0.</p><pre><code class="klipse-clojure nohighlight">(count "Hello")
;; ⇒ 5
</code></pre><pre><code class="klipse-clojure nohighlight">(count [1 2 3 4 5 6 7])
;; ⇒ 7
</code></pre><pre><code class="klipse-clojure nohighlight">(count nil)
;; ⇒ 0
</code></pre><p>Note that count does not return in constant time for all collections. This can be determined with <code>counted?</code>.
Keep in mind that lazy sequences must be realized to get a count of the items. This is often not intended and
can cause a variety of otherwise cryptic errors.</p><pre><code class="klipse-clojure nohighlight">(counted? "Hello")
;; ⇒ false
</code></pre><pre><code class="klipse-clojure nohighlight">;; will be fully realized when using (count (range 10))
(counted? (range 10))
;; ⇒ false
</code></pre><pre><code class="klipse-clojure nohighlight">;; Constant time return of (count)
(counted? [1 2 3 4 5])
;; ⇒ true
</code></pre><h3 id="conj">conj</h3><p><code>conj</code> is short for "conjoin". As the name implies, <code>conj</code> takes a collection and argument(s) and returns the collection with those arguments added.</p><p>Adding items to a collection occurs at different places depending on the concrete type of collection.</p><p>List addition occurs at the beginning of the list. This is because accessing the head of the list is a constant time operation, and accessing
the tail requires traversal of the entire list.</p><pre><code class="klipse-clojure nohighlight">(conj '(1 2) 3)
;; ⇒ (3 1 2)
</code></pre><p>Vectors have constant time access across the entire data structure. `'conj' thusly appends to the end of a vector.</p><pre><code class="klipse-clojure nohighlight">(conj [1 2] 3)
;; ⇒ [1 2 3]
</code></pre><p>Maps do not have guaranteed ordering, so the location that items are added is irrelevant. <code>conj</code> requires vectors of [key value] pairs to be
added to the map.</p><pre><code class="klipse-clojure nohighlight">(conj {:a 1 :b 2 :c 3} [:d 4])
;; ⇒ {:d 4, :a 1, :c 3, :b 2}
</code></pre><pre><code class="klipse-clojure nohighlight">(conj {:cats 1 :dogs 2} [:ants 400] [:giraffes 13])
;; ⇒ {:giraffes 13, :ants 400, :cats 1, :dogs 2}
</code></pre><p>Sets also do not have guaranteed ordering. <code>conj</code> returns a set with the item added. As the concept of sets implies, added items will not duplicate equivalent items if they are present in the set.</p><pre><code class="klipse-clojure nohighlight">(conj #{1 4} 5)
;; ⇒ #{1 4 5}
</code></pre><pre><code class="klipse-clojure nohighlight">(conj #{:a :b :c} :b :c :d :e)
;; ⇒ #{:a :c :b :d :e}
</code></pre><h3 id="get">get</h3><p><code>get</code> returns the value for the specified key in a map or record, index of a vector or value in a set. If the key is not present,
<code>get</code> returns nil or a supplied default value.</p><pre><code class="klipse-clojure nohighlight">;; val of a key in a map
(get {:a 1 :b 2 :c 3} :b)
;; ⇒ 2
</code></pre><pre><code class="klipse-clojure nohighlight">;; index of a vector
(get [10 15 20 25] 2)
;; ⇒ 20
</code></pre><pre><code class="klipse-clojure nohighlight">;; in a set, returns the value itself if present
(get #{1 10 100 2 20 200} 1)
;; ⇒ 1
```klipse-clojure
;; returns nil if key is not present
(get {:a 1 :b 2} :c)
;; ⇒ nil
</code></pre><pre><code class="klipse-clojure nohighlight">;; vector does not have an _index_ of 4. nil is returned
(get [1 2 3 4] 4)
;; ⇒ nil
</code></pre><pre><code class="klipse-clojure nohighlight">(defrecord Hand [index middle ring pinky thumb])
(get (Hand. 3 4 3.5 2 2) :index)
;; ⇒ 3
</code></pre><p><code>get</code> also supports a default return value supplied as the last argument.</p><pre><code class="klipse-clojure nohighlight">;; index 4 does not exist. return default value
(get [1 2 3 4] 4 "Not Found")
;; ⇒ "Not Found"
</code></pre><pre><code class="klipse-clojure nohighlight">;; key :c does not exist, so return default value of 3
(get {:a 1 :b 2} :c 3)
;; ⇒ 3
</code></pre><h3 id="assoc">assoc</h3><p><code>assoc</code> takes a key and a value and returns a collection of the same type as the supplied collection with the key mapped to the new value.</p><p><code>assoc</code> is similar to <code>get</code> in how it works with maps, records or vectors. When applied to a map or record, the same type is returned with the key/value pairs added or modified. When applied to a vector, a vector is returned with the key acting as an index and the index being replaced by the value.</p><p>Since maps and records can not contain multiple equivalent keys, supplying <code>assoc</code> with a key/value that exists in the one will cause <code>assoc</code> to return modify the key at that value in the result and not duplicate the key.</p><pre><code class="klipse-clojure nohighlight">(assoc {:a 1} :b 2)
;; ⇒ {:b 2, :a 1}
</code></pre><pre><code class="klipse-clojure nohighlight">(assoc {:a 1 :b 45 :c 3} :b 2)
;; ⇒ {:a 1, :c 3, :b 2}
</code></pre><pre><code class="klipse-clojure nohighlight">(defrecord Hand [index middle ring pinky thumb])
(assoc (Hand. 3 4 3.5 2 2) :index 3.75)
;; ⇒ #user.Hand{:index 3.75, :middle 4, :ring 3.5, :pinky 2, :thumb 2}
</code></pre><p>When using <code>assoc</code> with a vector, the key is the index and the value is the value to assign to that index in the returned vector.
The key must be &lt;= (count vector) or an index out of bounds error will occur.</p><pre><code class="klipse-clojure nohighlight">(assoc [1 2 76] 2 3) ; ⇒ [1 2 3]
</code></pre><pre><code class="klipse-clojure nohighlight">;; index 5 does not exist. valid indexes for this vector are: 0, 1, 2
(assoc [1 2 3] 5 6)
;; the error here is slightly different in Clojure/Script
</code></pre><p>When the key is equal to (count vector) <code>assoc</code> will add an item to the vector.</p><pre><code class="klipse-clojure nohighlight">(assoc [1 2 3] 3 4) ; ⇒ [1 2 3 4]
</code></pre><h3 id="dissoc">dissoc</h3><p><code>dissoc</code> returns a map with the supplied keys, and subsequently their values, removed. Unlike <code>assoc</code>, <code>dissoc</code> does not work on vectors. When a record is provided, <code>dissoc</code> returns a map. For similar functionality with vectors, see <code>subvec</code> and <code>concat</code>.</p><pre><code class="klipse-clojure nohighlight">(dissoc {:a 1 :b 2 :c 3} :b)
;; ⇒ {:a 1, :c 3}
</code></pre><pre><code class="klipse-clojure nohighlight">(dissoc {:a 1 :b 14 :c 390 :d 75 :e 2 :f 51} :b :c :e)
;; ⇒ {:a 1, :f 51, :d 75}
</code></pre><pre><code class="klipse-clojure nohighlight">;; note that a map is returned, not a record.
(defrecord Hand [index middle ring pinky thumb])
;; always be careful with the bandsaw!
(dissoc (Hand. 3 4 3.5 2 2) :ring)
;; ⇒ {:index 3, :middle 4, :pinky 2, :thumb 2}
</code></pre><h3 id="first">first</h3><p><code>first</code> returns the first item in the collection. <code>first</code> returns nil if the argument is empty or is nil.</p><p>Note that for collections that do not guarantee order like some maps and sets, the behaviour of <code>first</code> should not be relied on.</p><pre><code class="klipse-clojure nohighlight">(first (range 10))
;; ⇒ 0
</code></pre><pre><code class="klipse-clojure nohighlight">(first [:floor :piano :seagull])
;; ⇒ :floor
</code></pre><pre><code class="klipse-clojure nohighlight">(first [])
;; ⇒ nil
</code></pre><h3 id="rest">rest</h3><p><code>rest</code> returns a seq of items starting with the second element in the collection. <code>rest</code> returns an empty seq if the collection only contains a single item.</p><p><code>rest</code> should also not be relied on when using maps and sets unless you are sure ordering is guaranteed.</p><pre><code class="klipse-clojure nohighlight">(rest [13 1 16 -4])
;; ⇒ (1 16 -4)
</code></pre><pre><code class="klipse-clojure nohighlight">(rest '(:french-fry))
;; ⇒ '()
</code></pre><p>The behaviour of <code>rest</code> should be contrasted with <code>next</code>. <code>next</code> returns nil if the collection only has a single item. This is important when considering "truthiness" of values since an empty seq is "true" but nil is not.</p><pre><code class="klipse-clojure nohighlight">(if (rest '("stuff"))
(println "Does this print?"))
;; yes, it prints.
</code></pre><pre><code class="clojure">;; NEVER FINISHES EXECUTION!!!
;; "done" is never reached because (rest x) is always a "true" value
(defn inf
[x]
(if (rest x)
(inf (rest x))
"done"))
</code></pre><h3 id="empty">empty?</h3><p><code>empty?</code> returns true if the collection has no items, or false if it has 1 or more items.</p><pre><code class="klipse-clojure nohighlight">(empty? [])
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">(empty? '(1 2 3))
;; ⇒ false
</code></pre><p>Do not confuse <code>empty?</code> with <code>empty</code>. This can be a source of great confusion:</p><pre><code class="klipse-clojure nohighlight">(if (empty [1 2 3]) ;; empty returns an empty seq, which is true! use empty? here.
"It's empty"
"It's not empty")
;; ⇒ "It's empty"
</code></pre><h3 id="empty-1">empty</h3><p><code>empty</code> returns an empty collection of the same type as the collection provided.</p><pre><code class="klipse-clojure nohighlight">(empty [1 2 3])
;; ⇒ []
</code></pre><pre><code class="klipse-clojure nohighlight">(empty {:a 1 :b 2 :c 3})
;; ⇒ {}
</code></pre><h3 id="not-empty">not-empty</h3><p><code>not-empty</code> returns nil if the collection has no items. If the collection contains items, the collection is returned.</p><pre><code class="klipse-clojure nohighlight">(not-empty '(:mice :elephants :children))
;; ⇒ (:mice :elephants :children)
</code></pre><pre><code class="klipse-clojure nohighlight">(not-empty '())
;; ⇒ nil
</code></pre><h3 id="contains">contains?</h3><p><code>contains</code> returns true if the provided <em>key</em> is present in a collection. <code>contains</code> is similar to <code>get</code> in that vectors treat the key as an index. <code>contains</code> will always return false for lists.</p><pre><code class="klipse-clojure nohighlight">(contains? {:a 1 :b 2 :c 3} :c)
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">;; true if index 2 exists
(contains? ["John" "Mary" "Paul"] 2)
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">;; false if index 5 does not exist
(contains? ["John" "Mary" "Paul"] 5)
;; ⇒ false
</code></pre><pre><code class="klipse-clojure nohighlight">;; "Paul" does not exist as an index
(contains? ["John" "Mary" "Paul"] "Paul")
;; ⇒ false
</code></pre><pre><code class="klipse-clojure nohighlight">;; lists are not supported. contains? won't traverse a collection for a result.
(contains? '(1 2 3) 0)
;; ⇒ java.lang.IllegalArgumentException: contains? not supported on type: clojure.lang.PersistentList
</code></pre><h3 id="some">some</h3><p><code>some</code> will apply a predicate to each value in a collection until a non-false/nil result is returned then immediately return that result.</p><p>Since collections are "true" values, this makes it possible to return the first result itself rather than simply <code>true</code>.</p><pre><code class="klipse-clojure nohighlight">(some even? [1 2 3 4 5])
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">;; predicate returns the value rather than simply true
(some #(if (even? %) %) [1 2 3 4 5])
;; ⇒ 2
</code></pre><p>Since maps can be used as functions, you can use a map as a predicate. This will return the value of the first key in the collection that is also in the map.</p><pre><code class="klipse-clojure nohighlight">(some {:a 1 :b 5} [:h :k :d :b])
;; ⇒ 5
</code></pre><p>Sets can also be used as functions and will return the first item in the collection that is present in the set.</p><pre><code class="klipse-clojure nohighlight">(some #{4} (range 20))
;; ⇒ 4
</code></pre><h3 id="every">every?</h3><p><code>every</code> returns true if the predicate returns true for every item in the collection, otherwise it returns false.</p><pre><code class="klipse-clojure nohighlight">(every? even? (range 0 10 2))
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">;; set can be used to see if collection only contains items in the set.
(every? #{2 3 4} [2 3 4 2 3 4])
;; ⇒ true
</code></pre><h3 id="map">map</h3><p><code>map</code> is used to sequence of values and generate a new sequence of
values.</p><p>Essentially, you're creating a <em>mapping</em> from an old sequence of values
to a new sequence of values.</p><pre><code class="klipse-clojure nohighlight">(def numbers
(range 1 10))
;; ⇒ (1 2 3 4 5 6 7 8 9)
</code></pre><pre><code class="klipse-clojure nohighlight">(map (partial * 2) numbers)
;; ⇒ (2 4 6 8 10 12 14 16 18)
</code></pre><pre><code class="klipse-clojure nohighlight">(def scores
{:clojure 10
:scala 9
:jruby 8})
(map #(str "Team " (name (key %)) " has scored " (val %)) scores)
;; ⇒ ("Team scala has scored 9" "Team jruby has scored 8" "Team clojure has scored 10")
</code></pre><h3 id="reduce">reduce</h3><p><code>reduce</code> takes a sequence of values and a function. It applies that
function repeatedly with the sequence of values to <em>reduce</em> it to a
single value.</p><pre><code class="klipse-clojure nohighlight">(def numbers
(range 1 10))
;; ⇒ (1 2 3 4 5 6 7 8 9)
</code></pre><pre><code class="klipse-clojure nohighlight">(reduce + numbers)
;; ⇒ 45
</code></pre><pre><code class="klipse-clojure nohighlight">(def scores
{:clojure 10
:scala 9
:jruby 8})
(reduce + (vals scores))
;; ⇒ 27
</code></pre><pre><code class="klipse-clojure nohighlight">;; Provide an initial value for the calculation
(reduce + 10 (vals scores))
;; ⇒ 37
</code></pre><h3 id="filter">filter</h3><p><code>filter</code> returns a lazy sequence of items that return <code>true</code> for the provided predicate. Contrast to <code>remove</code>.</p><pre><code class="klipse-clojure nohighlight">(filter even? (range 10))
;; ⇒ (0 2 4 6 8)
</code></pre><pre><code class="klipse-clojure nohighlight">(filter #(if (&lt; (count %) 5) %) ["Paul" "Celery" "Computer" "Rudd" "Tayne"])
;; ⇒ ("Paul" "Rudd")
</code></pre><p>When using sets with <code>filter</code>, remember that if nil or false is in the set and in the collection, then the predicate will return itself: <code>nil</code>.</p><p>In this example, when nil and false are tested with the predicate, the predicate returns nil. This is because if the item is present in the set it is returned. This will cause that item to /not/ be included in the returned lazy-sequence.</p><pre><code class="klipse-clojure nohighlight">(filter #{:nothing :something nil}
[:nothing :something :things :someone nil false :pigeons])
;; ⇒ (:nothing :something)
</code></pre><h3 id="remove">remove</h3><p><code>remove</code> returns a lazy sequence of items that return <code>false</code> or <code>nil</code> for the provided predicate. Contrast to <code>filter</code>.</p><pre><code class="klipse-clojure nohighlight">(remove even? (range 10))
;; ⇒ (1 3 5 7 9)
</code></pre><pre><code class="klipse-clojure nohighlight">;; relative complement. probably useless?
(remove {:a 1 :b 2} [:h :k :z :b :s])
;; ⇒ (:h :k :z :s)
</code></pre><p>When using sets with <code>remove</code>, remember that if nil or false is in the set and in the collection, then the predicate will return itself: <code>nil</code>.
This will cause that item to be included in the returned lazy sequence.</p><p>In this example, when nil and false are tested with the predicate, the predicate returns nil. This is because if the item is present in the set it is returned.</p><pre><code class="klipse-clojure nohighlight">(remove #{:nothing :something nil}
[:nothing :something :things :someone nil false :pigeons])
;; ⇒ (:things :someone nil false :pigeons)
</code></pre><h3 id="iterate">iterate</h3><p><code>iterate</code> takes a function and an initial value, returns the result of
applying the function on that initial value, then applies the function
again on the resultant value, and repeats forever, lazily. Note that the
function <em>iterates</em> on the value.</p><pre><code class="klipse-clojure nohighlight">(take 5 (iterate inc 1))
;; ⇒ (1 2 3 4 5)
</code></pre><pre><code class="klipse-clojure nohighlight">(defn multiply-by-two
[value]
(* 2 value))
(take 10 (iterate multiply-by-two 1))
;; ⇒ (1 2 4 8 16 32 64 128 256 512)
</code></pre><h3 id="get-in">get-in</h3><p><code>get-in</code> is used to <em>get</em> a value that is deep <em>inside</em> a data
structure.</p><p>You have to provide the data structure and a sequence of keys, where a
key is valid at each subsequent level of the nested data structure.</p><p>If the sequence of keys does not lead to a valid path, <code>nil</code> is
returned.</p><pre><code class="klipse-clojure nohighlight">(def family
{:dad {:shirt 5
:pants 6
:shoes 4}
:mom {:dress {:work 6
:casual 7}
:book 3}
:son {:toy 5
:homework 1}})
</code></pre><pre><code class="klipse-clojure nohighlight">(get-in family [:dad :shirt])
;; ⇒ 5
</code></pre><pre><code class="klipse-clojure nohighlight">(get-in family [:mom :dress])
;; ⇒ {:work 6, :casual 7}
</code></pre><pre><code class="klipse-clojure nohighlight">(get-in family [:mom :dress :casual])
;; ⇒ 7
</code></pre><pre><code class="klipse-clojure nohighlight">(get-in family [:son :pants])
;; ⇒ nil
```klipse-clojure
(def locations
[:office :home :school])
(get-in locations [1])
;; ⇒ :home
</code></pre><h3 id="update-in">update-in</h3><p><code>update-in</code> is used to <em>update</em> a value deep inside a structure
<em>in-place</em>.</p><p>Note that since data structures are immutable, it only returns a
"modified" data structure, it does not actually alter the original
reference.</p><p>The "update" function takes the old value and returns a new value which
<code>update-in</code> uses in the new modified data structure.</p><pre><code class="klipse-clojure nohighlight">(def family
{:dad {:shirt 5
:pants 6
:shoes 4}
:mom {:dress {:work 6
:casual 7}
:book 3}
:son {:toy 5
:homework 1}})
</code></pre><pre><code class="klipse-clojure nohighlight">(update-in family [:dad :pants] inc)
;; ⇒ {:son {:toy 5, :homework 1}, :mom {:dress {:work 6, :casual 7}, :book 3}, :dad {:shoes 4, :shirt 5, :pants 7}}
</code></pre><p>Notice that "pants" gets incremented</p><pre><code class="klipse-clojure nohighlight">(def locations
[:office :home :school])
(update-in locations [2] #(keyword (str "high-" (name %))))
;; ⇒ [:office :home :high-school]
</code></pre><h3 id="assoc-in">assoc-in</h3><p><code>assoc-in</code> is used to <em>associate</em> a new value deep inside a structure
<em>in-place</em>.</p><p>Note that since data structures are immutable, it only returns a
"modified" data structure, it does not actually alter the original
reference.</p><p>Note the difference between <code>update-in</code> and <code>assoc-in</code>: <code>update-in</code>
takes a function that applies on the old value to return a new value,
whereas <code>assoc-in</code> takes a new value as-is.</p><pre><code class="klipse-clojure nohighlight">(def family
{:dad {:shirt 5
:pants 6
:shoes 4}
:mom {:dress {:work 6
:casual 7}
:book 3}
:son {:toy 5
:homework 1}})
</code></pre><pre><code class="klipse-clojure nohighlight">(assoc-in family [:son :crayon] 3)
;; ⇒ {:son {:toy 5, :crayon 3, :homework 1}, :mom {:dress {:work 6, :casual 7}, :book 3}, :dad {:shoes 4, :shirt 5, :pants 6}}
</code></pre><pre><code class="klipse-clojure nohighlight">(def locations
[:office :home :school])
(assoc-in locations [3] :high-school)
;; ⇒ [:office :home :school :high-school]
</code></pre><h3 id="keys">keys</h3><p><code>keys</code> returns a sequence of the keys in a map or record.</p><pre><code class="klipse-clojure nohighlight">(keys {1 "one" 2 "two" 3 "three"})
;; ⇒ (1 2 3)
</code></pre><pre><code class="klipse-clojure nohighlight">(defrecord Hand [index middle ring pinky thumb])
(keys (Hand. 2 4 3 1 2))
;; ⇒ (:index :middle :ring :pinky :thumb)
</code></pre><h3 id="vals">vals</h3><p><code>vals</code> returns a sequence of vals in a map or record.</p><pre><code class="klipse-clojure nohighlight">(vals {:meows 20 :barks 2 :moos 5})
;; ⇒ (5 2 20)
</code></pre><pre><code class="klipse-clojure nohighlight">(defrecord Hand [index middle ring pinky thumb])
(vals (Hand. 1 2 3 4 5))
;; ⇒ (1 2 3 4 5)
</code></pre><h3 id="select-keys">select-keys</h3><p><code>select-keys</code> is used to extract a subset of a map:</p><pre><code class="klipse-clojure nohighlight">(def family
{:dad {:shirt 5
:pant 6
:shoes 4}
:mom {:dress {:work 6
:casual 7}
:book 3}
:son {:toy 5
:homework 1}})
</code></pre><pre><code class="klipse-clojure nohighlight">(select-keys family [:dad])
;; ⇒ {:dad {:shoes 4, :shirt 5, :pant 6}}
</code></pre><pre><code class="klipse-clojure nohighlight">(select-keys family [:mom :son])
;; ⇒ {:son {:toy 5, :homework 1}, :mom {:dress {:work 6, :casual 7}, :book 3}}
</code></pre><h3 id="take">take</h3><p><code>take</code> returns a lazy sequence of the first <code>n</code> items of a collection <code>coll</code>.</p><pre><code class="klipse-clojure nohighlight">(take 3 [1 3 5 7 9])
;; ⇒ (1 3 5)
</code></pre><pre><code class="klipse-clojure nohighlight">(type (take 3 (range)))
;; ⇒ clojure.lang.LazySeq
</code></pre><p>If there are fewer than <code>n</code> items in <code>coll</code>, all items will be returned.</p><pre><code class="klipse-clojure nohighlight">(take 5 [1 2 3])
;; ⇒ (1 2 3)
</code></pre><pre><code class="klipse-clojure nohighlight">(take 3 nil)
;; ⇒ ()
</code></pre><h3 id="drop">drop</h3><p><code>drop</code> drops <code>n</code> items from a collection <code>coll</code> and returns a lazy sequence of the rest of it.</p><pre><code class="klipse-clojure nohighlight">(drop 3 '(0 1 2 3 4 5 6))
;; ⇒ (3 4 5 6)
</code></pre><pre><code class="klipse-clojure nohighlight">(drop 2 [1 2])
;; ⇒ ()
</code></pre><pre><code class="klipse-clojure nohighlight">(drop 2 nil)
;; ⇒ ()
</code></pre><h3 id="take-while">take-while</h3><p><code>take-while</code> returns a lazy sequence of items from a collection as long
as the predicate returns <code>true</code> for each item:</p><pre><code class="klipse-clojure nohighlight">(take-while #(&lt; % 5) (range))
;; ⇒ (0 1 2 3 4)
</code></pre><h3 id="drop-while">drop-while</h3><p><code>drop-while</code> drops items from a collection as long as the predicate
returns <code>false</code> for the item and when the first non-false item is found,
it returns a lazy sequence from that item onwards:</p><pre><code class="klipse-clojure nohighlight">(drop-while #(&lt; % 5) (range 10))
;; ⇒ (5 6 7 8 9)
</code></pre><h2 id="transients">Transients</h2><p>Clojure data structures are immutable, they do not change. Mutating them produces
a new data structure that internally has structural sharing with the original
one. This makes a whole class of concurrency hazards go away but has some
performance penalty and additional GC pressure.</p><p>For cases when raw performance for a piece of code is more important than safety,
Clojure provides mutable versions of vectors and unsorted maps. They are known
as <em>transients</em> and should only be used for locals and as an optimization
technique after profiling.</p><p>Transients are produced from immutable data structures using the <code>clojure.core/transient</code>
function:</p><pre><code class="klipse-clojure nohighlight">(let [m (transient {})]
(assoc! m :key "value") ;; mutates the transient in place!
(count m))
;; ⇒ 1
</code></pre><p>Note that <code>clojure.core/transient</code> does not affect nested collections, for
example, values in a map of keywords to vectors.</p><p>To mutate transients, use <code>clojure.core/assoc!</code>, <code>clojure.core/dissoc!</code> and
<code>clojure.core/conj!</code>. The exclamation point at the end hints that these
functions work on transients and modify data structures in place, which
is not safe of data structures are shared between threads.</p><p>To create an immutable data structure out of a transient, use <code>clojure.core/persistent!</code>:</p><pre><code class="klipse-clojure nohighlight">(let [m (transient {})]
(assoc! m :key "value")
(persistent! m)) ;; ⇒ {:key "value"}
</code></pre><p>In conclusion: use transients only as an optimization technique and only
after profiling and identifying hot spots in your code. Guessing is the
shortest way we know to blowing the performance.</p><h2 id="custom-collections-and-sequences">Custom Collections and Sequences</h2><p>It is possible to develop custom collection types in Clojure or Java and have
<code>clojure.core</code> functions work on them just like they do on builtin types.</p><p>TBD: <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></p><h2 id="wrapping-up">Wrapping Up</h2><p>When working with Clojure, it is common to operate and transform collections and sequences.
Clojure's core library unify operations on collections and sequences where possible.
This extends to Java collections, arrays and iterable objects for seamless interoperability.</p><p>Most of the time, whenever you need a function that transforms sequences, chances are, there is
one already that does that in <code>clojure.core</code> or you can compose more than one <code>clojure.core</code> function
to achieve the same result.</p><h2 id="contributors">Contributors</h2><p>Michael Klishin <a href="mailto:michael@defprotocol.org">michael@defprotocol.org</a>
Robert Randolph <a href="mailto:audiolabs@gmail.com">audiolabs@gmail.com</a>
satoru <a href="mailto:satorulogic@gmail.com">satorulogic@gmail.com</a></p>
<div id="prev-next">
<a href="../namespaces/index.html">&laquo; Clojure Namespaces and Vars</a>
||
<a href="../functions/index.html">Functions in Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../functions/index.html">Functions in Clojure</a></li>
<li><a href="../laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
<link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">
<script>
window.klipse_settings = {
"selector" : ".klipse-clojure"
};
</script>
<script src="https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"></script>
</body>
</html>

View file

@ -0,0 +1,755 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Concurrency and Parallelism in Clojure</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/concurrency_and_parallelism/" />
<meta property="og:title" content="Concurrency and Parallelism in Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/concurrency_and_parallelism/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Concurrency and Parallelism in Clojure</h2>
</div>
<p>This guide covers:</p><ul><li>Clojure's identity/value separation</li><li>Clojure reference types and their concurrency semantics: atoms, refs, agents, vars</li><li>Dereferencing</li><li>Delays, futures and promises</li><li>Watches and validators</li><li>How to use java.util.concurrent from Clojure</li><li>Other approaches to concurrency available on the JVM</li><li>Other topics related to concurrency</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5.</p><h2 id="before-you-read-this-guide">Before You Read This Guide</h2><p>This is one of the most hardcore guides of the entire Clojure documentation
project. It describes concepts that are simple but may seem foreign at first.
These concepts are some of the key points of Clojure
design. Understanding them may take some time for folks without
a concurrent programming background. Don't let this learning curve
discourage you.</p><p>If some parts are not clear, please ask for clarification <a href="https://groups.google.com/forum/?fromgroups#!forum/clojure">on the
mailing
list</a> or
<a href="https://github.com/clojure-doc/clojure-doc.github.io/issues">file an issue</a> on GitHub.
We will work hard on making this guide easy to follow with edits and
images to illustrate the concepts.</p><h2 id="introduction-and-terminology">Introduction and Terminology</h2><p>Before we get to the Clojure features related to concurrency, lets lay a foundation and briefly
cover some terminology.</p><table class="table-striped table-bordered table"><thead><tr><th>Term</th><th>Definition This Guide Uses</th></tr></thead><tbody><tr><td>Concurrency</td><td>When multiple threads are making progress, whether it is via time-slicing or parallelism</td></tr><tr><td>Parallelism</td><td>A condition that arises when at least two threads are executing simultaneously, e.g., on multiple cores or CPUs.</td></tr><tr><td>Shared State</td><td>When multiple threads of execution need to mutate (modify) one or more pieces of program state (e.g., variables, identities)</td></tr><tr><td>Mutable Data Structures</td><td>Data structures that, when changed, are updated "in place"</td></tr><tr><td>Immutable Data Structures</td><td>Data structures that, when changed, produce new data structures (copies), possibly with optimizations such as internal structural sharing</td></tr><tr><td>Concurrency Hazards</td><td>Conditions that occur in concurrent programs that prevent program from being correct (behaving the way its authors intended).</td></tr><tr><td>Shared Mutable State</td><td>When shared state is made of mutable data structures. A ripe ground for concurrency hazards.</td></tr></tbody></table><p>There are many concurrency hazards, some of the most common and well known are:</p><table class="table-striped table-bordered table"><thead><tr><th>Concurrency Hazard</th><th>Brief Description</th></tr></thead><tbody><tr><td>Race Condition</td><td>A condition when the outcome is dependent on timing or relative ordering of events</td></tr><tr><td>Deadlock</td><td>When two or more threads are waiting on each other to finish or release a shared resource, thus waiting forever and not making any progress</td></tr><tr><td>Livelock</td><td>When two or more threads are technically performing computation but not doing any useful work (not making progress), for example,
because they endlessly pass a piece of data to each other but never actually process it</td></tr><tr><td>Starvation</td><td>When a thread is not given regular access to a shared resource and cannot make progress.</td></tr></tbody></table><p>These hazards are not exclusive to threads and can happen with OS
processes, runtime processes and any other execution processes. They
are also not specific to a particular runtime or VM (e.g., the JVM) or
programming language. Admittedly, some languages make it significantly
easier to write correct, safe concurrent programs, but none are
completely immune to concurrency hazards. More often than not,
concurrency hazards are algorithmic problems, languages just encourage
or discourage certain practices and techniques.</p><p><em>Thread-safe</em> code is code that is always executed correctly and does
not suffer from concurrency hazards even when executed concurrently
from multiple threads.</p><h2 id="overview">Overview</h2><p>One of Clojure design goals was to make concurrent programming
easier. The thinking is that as modern CPUs add more and more cores
and the number of CPUs is increasing as well, the biggest contributor
to application throughput will come from making use of those
resources.</p><p>The key design decision was making Clojure data structures immutable
(persistent) and separating the concepts of <em>identity</em> and
<em>value</em>. The importance of immutability cannot be over-emphasized:
immutable values can be safely shared between threads, eliminate many
concurrency hazards, and ultimately make it easier for developers to
reason about their programs.</p><p>However, a language that only has immutable data structures and no way
to change (mutate) program state is not very useful. The
identity/value separation makes state mutations (e.g., incrementing a
counter or adding an element to a list) possible in ways that
have known guarantees with respect to concurrency. This separation largely
eliminates the need for explicit use of locks, which is possible in Clojure
but typically not necessary.</p><p>To put it another way: "changing variables" in Clojure happens
differently from many other languages; in ways that are predictable
from the concurrency perspective and which eliminate many concurrency hazards.</p><p>Next lets take a closer look to the identity/value separation.</p><h2 id="identityvalue-separation-on-state-and-identity">Identity/Value Separation ("on State and Identity")</h2><p>In Clojure, <em>values</em> are immutable. They never change. For example, a number is a value.
A map <code>{:language "Clojure"}</code> is a value. A vector with 3 elements is a value.</p><p>When you attempt to modify a value (a data structure), a new value is produced instead. These
are known as <em>persistent data structures</em> (the word "persistent" has nothing to do with
storing data on disk).</p><p>An <em>identity</em> is a named entity (e.g., a list of active chat group
members or a counter) that changes over time and at any given moment references a value.
For example, the current value of a counter may be <code>42</code>. After incrementing it, the value
is <code>43</code> but it is still the same counter --- the same identity. This is different from, say, Java
or Ruby, where variables serve as identities that (typically) point to a mutable value
and which are modified in place.</p><p><img src="https://clojure-doc.org/assets/images/language/concurrency_and_parallelism/identity_value.png" alt="identity_value" /></p><p>Identities in Clojure can be of several types, known as <em>reference types</em>.</p><h2 id="clojure-reference-types">Clojure Reference Types</h2><h3 id="overview-1">Overview</h3><p>In Clojure's world view, concurrent operations can be roughly
classified as coordinated or uncoordinated, and synchronous or
asynchronous. Different reference types in Clojure have their own
concurrency semantics and cover different kind of operations:</p><table class="table-bordered table"><thead><tr><th></th><th>Coordinated</th><th>Uncoordinated</th></tr></thead><tbody><tr><td style="font-weight: bold;">Synchronous</td><td><a href="index.html#refs">Refs</a></td><td><a href="index.html#atoms">Atoms</a></td></tr><tr><td style="font-weight: bold;">Asynchronous</td><td></td><td><a href="index.html#agents">Agents</a></td></tr></tbody></table><dl><dt>Coordinated</dt><dd>An operation that depends on cooperation from other operations (possibly, other operations at least do not interfere with it)
in order to produce correct results. For example, a banking operation that involves more than one account.
</dd><dt>Uncoordinated</dt><dd>An operation that does not affect other operations in any way. For example, when downloading 100 Web pages concurrently,
each operation does not affect the others.
</dd><dt>Synchronous</dt><dd>When the caller's thread waits, blocks, or sleeps until it has access to a given resource or context.</dd><dt>Asynchronous</dt><dd>Operations that can be started or scheduled without blocking the caller's thread.</dd></dl><p>One more reference type, <a href="index.html#vars">vars</a>, supports dynamic scoping and thread-local storage.</p><h3 id="atoms">Atoms</h3><p>Atoms are references that change atomically (changes become immediately visible to all threads,
changes are guaranteed to be synchronized by the JVM). If you come from a Java background,
atoms are basically atomic references from <code>java.util.concurrent</code> with a functional twist
to them. Atoms are identities that implement synchronous, uncoordinated, atomic updates.</p><p>Lets jump right in and demonstrate how atoms work using an example. We know that Clojure data
structures are immutable by default. Adding an element to a collection really produces a new
collection. In such case, how does one keep a shared list (say, of active connections to a server
or recently crawled URLs) and mutate it in a thread-safe manner? We will demonstrate how to
accomplish this with an atom.</p><p>To create an atom, use the <code>clojure.core/atom</code> function. Its argument will serve as the atom's
initial value:</p><pre><code class="clojure">(def currently-connected (atom []))
</code></pre><p>The line above makes the atom <code>currently-connected</code> an empty vector. To access an atom's value, use
<code>clojure.core/deref</code> or the <code>@atom</code> reader form:</p><pre><code class="clojure">(def currently-connected (atom []))
@currently-connected
;; ⇒ []
(deref currently-connected)
;; ⇒ []
currently-connected
;; ⇒ #&lt;Atom@614b6b5d: []&gt;
</code></pre><p>As the returned values demonstrate, the atom itself is a reference. To
access its current value, you <em>dereference</em> it. Dereferencing will be
covered in more detail later in this guide. For now, it is sufficient
to say that dereferencing returns the current value of an atom. (Other
Clojure reference types as well as a few specialized data structures
can be dereferenced as well.)</p><p>Locals can be atoms, too:</p><pre><code class="clojure">(let [xs (atom [])]
@xs)
;; ⇒ []
</code></pre><p>Now to the most interesting part: adding elements to the collection.</p><p>To mutate an atom, we can use <code>clojure.core/swap!</code>.</p><p><code>swap!</code> takes an atom, a function and optionally some other args, swaps the current value of the atom to be the return value of calling the function with the current value of the atom and the args:</p><pre><code class="clojure">(swap! currently-connected conj "chatty-joe")
;; ⇒ ["chatty-joe"]
currently-connected
;; ⇒ #&lt;Atom@614b6b5d: ["chatty-joe"]&gt;
@currently-connected
;; ⇒ ["chatty-joe"]
</code></pre><p>To demonstrate this graphically, initial atom state looks like this:</p><p><img src="https://clojure-doc.org/assets/images/language/concurrency_and_parallelism/atom_state1.png" alt="Atom state 1" /></p><p>and then we mutated it with <code>swap!</code>:</p><p><img src="https://clojure-doc.org/assets/images/language/concurrency_and_parallelism/atom_state2.png" alt="Atom state 2" /></p><p>For the readers familiar with the atomic types from the <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html">java.util.concurrent.atomic</a> package,
this should sound very familiar. The only difference is that instead of setting a value, atoms are mutated
with a function. This is both because Clojure is a functional language and because with this approach,
<code>clojure.core/swap!</code> can <em>retry the operation</em> safely. This implies that the function you provide to
<code>swap!</code> is <em>pure</em> (has no side effects).</p><p>Occasionally you will need to mutate the value of an atom the same way you would with atomic references in Java:
by setting them to a specific value. This is what <code>clojure.core/reset!</code> does. It takes an atom and the new value:</p><pre><code class="clojure">@currently-connected
;; ⇒ ["chatty-joe"]
(reset! currently-connected [])
;; ⇒ []
@currently-connected
;; ⇒ []
</code></pre><p><code>reset!</code> may be useful in test suites to reset an atom's state between test executions, but it should be
used sparingly in your implementation code. Consider using <code>swap!</code> first.</p><p><em>TBD: demonstrate retries under high update rates</em></p><h4 id="summary-and-use-cases">Summary and Use Cases</h4><p>Atoms is the most commonly used concurrent feature in Clojure. It covers many cases and lets developers
avoid explicit locking. Atoms cover a lot of use cases and are very fast. It's fair to say that
when you need uncoordinated reference types (e.g., not Software Transactional Memory), the rule of
thumb is, "start with an atom, then see".</p><p>It is not uncommon to initialize an atom in a local and then return it from the function and share
a piece of state with other functions and/or threads.</p><h3 id="agents">Agents</h3><p>Agents are references that are updated asynchronously: updates happen at a later, unknown point
in time, in a thread pool. Agents are identities that implement uncoordinated, asynchronous updates.</p><p>A small but useful example of using an agent is as a counter. For
example, suppose we want to track how often page downloads in a Web
crawler respond with 40x and 50x status codes. The simplest version
can look like this:</p><pre><code class="clojure">(def errors-counter (agent 0))
;; ⇒ #'user/errors-counter
errors-counter
;; ⇒ #&lt;Agent@6a6287b2: 0&gt;
@errors-counter
;; ⇒ 0
(deref errors-counter)
;; ⇒ 0
</code></pre><p>One can immediately make several observations: just like atoms, agents are references. To get
the current value of an agent, we need to <em>dereference</em> it using <code>clojure.core/deref</code> or
the <code>@agent</code> reader macro.</p><p>To mutate an agent, we use <code>clojure.core/send</code> and <code>clojure.core/send-off</code>:</p><pre><code class="clojure">@errors-counter
;; ⇒ 0
(send errors-counter inc)
;; ⇒ #&lt;Agent@6a6287b2: 0&gt;
@errors-counter
;; ⇒ 1
;; 10 is an additional parameter. The + function will be invoked as `(+ @errors-counter 10)`.
(send errors-counter + 10)
;; ⇒ #&lt;Agent@6a6287b2: 1&gt;
@errors-counter
;; ⇒ 11
</code></pre><p><code>send</code> and <code>send-off</code> are largely similar. The difference is in how they are implemented. <code>send</code> uses a
fixed-size thread pool so using blocking operations with it won't yield good throughput. <code>send-off</code>
uses a growing thread-pool so blocking operations is not a problem for it as long as there are resources
available to the JVM to create and run all the threads. On a 4-8 GB machine with 4 cores and stock
OS settings you can expect up to a couple of thousand I/O-bound threads to work without running
the system out of kernel resources.</p><h4 id="using-custom-executors-with-agents">Using Custom Executors With Agents</h4><p>Agents can be used (and abused) for arbitrary code execution in a thread pool. Because the default
thread pool Clojure maintains will not be a good fit for all use cases, Clojure 1.5 introduced
a function that lets you control what thread pool (executor) is used by <code>clojure.core/send</code>:
<code>clojure.core/set-agent-send-executor!</code>.</p><pre><code class="clojure">(import java.util.concurrent.Executors)
(set-agent-send-executor! (Executors/newFixedThreadPool 32))
;; clojure.core/send now will use the fixed size thread pool with 32 threads
</code></pre><p>The default thread pool size is <code>number of available CPU cores + 2</code>.</p><p><code>clojure.core/set-agent-send-off-executor!</code> is a similar function that controls what
thread pool <code>clojure.core/send-off</code> will use.</p><p>Finally, another new function in 1.5 is <code>clojure.core/send-via</code> which is like `` but lets you specify
an executor to be used on a case-by-case basis:</p><pre><code class="clojure">(import java.util.concurrent.Executors)
(def custom-pool (Executors/newFixedThreadPool 32))
;; just like clojure.core/send but will use custom-pool instead
;; of an internally maintained one
(send-via custom-pool stream-agent inc)
</code></pre><h3 id="agents-and-software-transactional-memory">Agents and Software Transactional Memory</h3><p>We haven't introduced refs and the concept of Software Transactional Memory yet. It will be covered later in this
guide. Here it's sufficient to mention that agents are STM-aware and can be safely used inside transactions.</p><h3 id="agents-and-error-handling">Agents and Error Handling</h3><p>Functions that modify an agent's state will not always return successfully in the real world. Sometimes they
will fail. For example:</p><pre><code class="clojure">@errors-counter
;; ⇒ 11
(send errors-counter / 0)
;; Evaluation aborted.
;; ⇒ nil
</code></pre><p>This puts the agent into the <em>failed</em> state. Failed agents will re-raise the exception that caused them
to fail every time their state changed is attempted:</p><pre><code class="clojure">(send errors-counter / 0)
;; ⇒ #&lt;Agent@6a6287b2: 10&gt;
(send errors-counter inc)
;; Evaluation aborted.
</code></pre><p>To access the exception that occured during the agent's state mutation, use <code>clojure.core/agent-error</code>:</p><pre><code class="clojure">(send errors-counter / 0)
;; Evaluation aborted.
;; ⇒ nil
(agent-error errors-counter)
;; ⇒ #&lt;ArithmeticException java.lang.ArithmeticException: Divide by zero&gt;
</code></pre><p>It returns an exception. Agents can be restarted with <code>clojure.core/restart-agent</code> that takes an agent
and a new initial value:</p><pre><code class="clojure">(restart-agent errors-counter 0)
;; ⇒ 0
(send errors-counter + 10)
;; ⇒ #&lt;Agent@6a6287b2: 0&gt;
@errors-counter
;; ⇒ 10
</code></pre><p>If you'd prefer an agent to ignore exceptions instead of going into the <em>failure mode</em>, <code>clojure.core/agent</code>
takes an option that controls this behavior: <code>:error-mode</code>. Because completely ignoring errors is rarely a good
idea, when the error mode is set to <code>:continue</code> you must also pass an error handler function:</p><pre><code class="clojure">(def errors-counter (agent 0
:error-mode :continue
:error-handler (fn [failed-agent ^Exception exception]
(println (.getMessage exception)))))
;; ⇒ #'user/errors-counter
(send errors-counter inc)
;; ⇒ #&lt;Agent@5620e147: 1&gt;
(send errors-counter inc)
;; ⇒ #&lt;Agent@5620e147: 2&gt;
(send errors-counter / 0)
;; output: "Divide by zero"
;; ⇒ #&lt;Agent@5620e147: 2&gt;
(send errors-counter inc)
;; ⇒ #&lt;Agent@5620e147: 3&gt;
@errors-counter
;; ⇒ 3
</code></pre><p>The handler function takes two arguments: an agent and the exception that occured.</p><h4 id="summary-and-use-cases-1">Summary and Use Cases</h4><p>Agents are asynchronously updated references. They can be used for anything that does
not require strict consistency for reads:</p><ul><li>Counters (e.g. message rates in event processing)</li><li>Collections (e.g. recently processed events)</li></ul><p>Agents can be used for offloading arbitrary computations to a thread pool, however,
only starting with Clojure 1.5 they can provide the same flexiblity as JDK executors
(thread pools).</p><h3 id="refs">Refs</h3><p>Refs are the only <em>coordinated</em> reference type Clojure has. They help ensure that multiple
identities can be modified concurrently within a <em><a href="https://clojure-doc.org/articles/language/concurrency_and_parallelism/glossary.html#transaction">transaction</a></em>:</p><ul><li>Either all refs are modified or none are</li><li>No race conditions between involved refs</li><li>No possibility of deadlocks between involved refs</li></ul><p>Refs provide ACI of <a href="http://en.wikipedia.org/wiki/ACID">ACID</a>. Refs
are backed by Clojure's implementation of <a href="https://clojure-doc.org/articles/language/concurrency_and_parallelism/glossary.html#stm"><em>software transactional
memory</em> (STM)</a>.</p><p>To instantiate a ref, use the <code>clojure.core/ref</code> function:</p><pre><code class="clojure">(def account-a (ref 0))
;; ⇒ #'user/account-a
(def account-b (ref 0))
;; ⇒ #'user/account-b
</code></pre><p>Like atoms and agents covered earlier, to get the current value of a ref, use <code>clojure.core/deref</code> or the "<code>@</code>"
reader macro:</p><pre><code class="clojure">(deref account-a)
;; ⇒ 0
@account-b
;; ⇒ 0
</code></pre><p>Refs are for coordinated concurrent operations and so it does not make much sense to use a single ref
(in that case, an atom would be sufficient). Refs are modified in a transaction in the <code>clojure.core/dosync</code>
body.</p><p><code>clojure.core/dosync</code> starts a transaction, performs all modifications and commits changes. If a concurrently
running transaction modifies a ref in the current transaction before the current transaction commits,
the current transaction will be <em>retried</em> to make sure that the most recent value of the modified
ref is used.</p><p><em>TBD: a picture that visualizes retries and serializability.</em></p><h4 id="alter">alter</h4><p>Refs are modified using <code>clojure.core/alter</code> which is very similar to
<code>clojure.core/swap!</code> in the arguments it takes: a ref, a function that
takes an old value and returns a new value of the ref, and any number
of optional arguments to pass to the function.</p><p>In the following example, two refs are initialized at 1000,
representing two bank accounts. Then 100 units are transferred from
one account to the other, atomically:</p><pre><code class="clojure">(def account-a (ref 1000))
;; ⇒ #'user/account-a
(def account-b (ref 1000))
;; ⇒ #'user/account-b
(dosync
;; will be executed as (+ @account-a 100)
(alter account-a + 100)
;; will be executed as (- @account-b 100)
(alter account-b - 100))
;; ⇒ 900
@account-a
;; ⇒ 1100
@account-b
;; ⇒ 900
</code></pre><h4 id="conflicts-and-retries">Conflicts and Retries</h4><p><em>TBD: explain transaction conflicts, demonstrate transaction retries</em></p><h4 id="commute">commute</h4><p>With a high number of concurrently running transactions, retries
overhead can become noticeable. Some modifications, however, can be
applied in any order. Clojure's STM implementation acknowledges this
fact and provides an alternative way to modify refs:
<code>clojure.core/commute</code>. <code>commute</code> must only be used for operations
that <a href="http://mathforum.org/dr.math/faq/faq.property.glossary.html#commutative">commute in the mathematical
sense</a>:
the order can be changed without affecting the result. For example,
addition is commutative (1 + 10 produces the same result as 10 + 1)
but substraction is not (1 10 does not equal 10 1).</p><p><code>clojure.core/commute</code> has the same signature as <code>clojure.core/alter</code>:</p><pre><code class="clojure">@account-a
;; ⇒ 1100
@account-b
;; ⇒ 900
(dosync
(commute account-a + 300)
(commute account-b + 300))
;; ⇒ 1200
@account-a
;; ⇒ 1400
@account-b
;; ⇒ 1200
</code></pre><p>Note that a change made to a ref by <code>commute</code> will never cause a transaction
to retry. <code>commute</code> does not cause <em>transaction conflicts</em>.</p><h4 id="using-refs-with-clojure-data-structures">Using Refs With Clojure Data Structures</h4><p><em>TBD: demonstrate more complex changes, e.g., to game characters</em></p><h4 id="limitations-of-refs">Limitations of Refs</h4><p>Software transactional memory is a powerful but highly specialized tool. Because transactions can be retried,
you must only use pure functions with STM. I/O operations cannot be undone by the runtime and very often are
not <a href="https://clojure-doc.org/articles/language/concurrency_and_parallelism/glossary.html#idempotent">idempotent</a>.</p><p>Structuring your application code as <em>pure core</em> and <em>edge code</em> that interacts with the user or other
services (performing I/O operations and other side-effects) helps with this. In that case, the pure core
can use STM without issues.</p><p>For example, in a Web or network server, incoming requests are the edge code: they do I/O. The pure core
is then called to modify server state, do any calculations necessary, return a result that is returned
back to the client by the edge code:</p><p><em>TBD: a picture to demonstrate</em></p><p>Unlike some other languages and runtimes (for example, Haskell), Clojure <em>will not prevent you from
doing I/O in transactions</em>. It is left as a matter of discipline on the programmer's part. It does provide
a helper function, though: <code>clojure.core/io!</code> will raise an exception if there is an STM transaction
running and has no effect otherwise.</p><p>First, an example with pure code:</p><pre><code class="clojure">(io!
;; pure code, clojure.core/io! has no effect
(reduce + (range 0 100)))
;; ⇒ 4950
</code></pre><p>And an example that invokes functions that are guarded with <code>clojure.core/io!</code> in an STM
transaction:</p><pre><code class="clojure">(defn render-results
"Prints results to the standard output"
[]
(io!
(println "Results:")
(comment ...)))
;; ⇒ #'user/render-results
(dosync
(alter account-a + 100)
(alter account-b - 100)
(render-results))
;; throws java.lang.IllegalStateException, "I/O in transaction!"
</code></pre><h4 id="summary-and-use-cases-2">Summary and Use Cases</h4><p><em>TBD</em></p><h3 id="vars">Vars</h3><p>Vars are the reference type you are already familiar with. You define them via the <code>def</code> special form:</p><pre><code class="clojure">(def url "http://en.wikipedia.org/wiki/Margarita")
</code></pre><p>Functions defined via <code>defn</code> are also stored in vars. Vars can be dynamically scoped. They have
<em>root bindings</em> that are initially visible to all threads. When defining a var
with <code>def</code>, you define a var that only has root binding, so its value will be the same no matter
what thread you use it from:</p><pre><code class="clojure">(def url "http://en.wikipedia.org/wiki/Margarita")
;; ⇒ #'user/url
(.start (Thread. (fn []
(println (format "url is %s" url)))))
;; outputs "url is http://en.wikipedia.org/wiki/Margarita"
;; ⇒ nil
(.start (Thread. (fn []
(println (format "url is %s" url)))))
;; outputs "url is http://en.wikipedia.org/wiki/Margarita"
;; ⇒ nil
</code></pre><h4 id="dynamic-scoping-and-thread-local-bindings">Dynamic Scoping and Thread-local Bindings</h4><p>To temporarily change var value, we need to make the var dynamic by adding <code>:dynamic true</code> to its
metadata and then use <code>clojure.core/binding</code>:</p><pre><code class="clojure">(def ^:dynamic *url* "http://en.wikipedia.org/wiki/Margarita")
;; ⇒ #'user/*url*
(println (format "*url* is now %s" *url*))
;; outputs "*url* is now http://en.wikipedia.org/wiki/Margarita"
(binding [*url* "http://en.wikipedia.org/wiki/Cointreau"]
(println (format "*url* is now %s" *url*)))
;; outputs "*url* is now http://en.wikipedia.org/wiki/Cointreau"
;; ⇒ nil
</code></pre><p>Note that, by convention, vars which are supposed to or may be dynamically scoped are named with leading
and trailing asterisks <code>*</code> (often referred to as "earmuffs").</p><p>In the example above, <code>binding</code> temporarily changed the var's current value to a different URL. But that happened only
in the same thread as the var was originally defined in. What makes vars interesting from the concurrency
point of view is that their bindings can be <em>thread-local</em> (yes, if you are familiar with thread-local variables
in Java or Ruby, it is very similar and serves largely the same purpose). To demonstrate, let's change
the example to spin up 3 threads and alter the var's value from them:</p><pre><code class="clojure">(def ^:dynamic *url* "http://en.wikipedia.org/wiki/Margarita")
;; ⇒ #'user/*url*
(println (format "*url* is now %s" *url*))
;; outputs "*url* is now http://en.wikipedia.org/wiki/Margarita"
;; ⇒ nil
(.start (Thread. (fn []
(binding [*url* "http://en.wikipedia.org/wiki/Cointreau"]
(println (format "*url* is now %s" *url*))))))
;; outputs "*url* is now http://en.wikipedia.org/wiki/Cointreau"
;; ⇒ nil
(.start (Thread. (fn []
(binding [*url* "http://en.wikipedia.org/wiki/Guignolet"]
(println (format "*url* is now %s" *url*))))))
;; outputs "*url* is now http://en.wikipedia.org/wiki/Guignolet"
;; ⇒ nil
(.start (Thread. (fn []
(binding [*url* "http://en.wikipedia.org/wiki/Apéritif"]
(println (format "*url* is now %s" *url*))))))
;; outputs "*url* is now http://en.wikipedia.org/wiki/Apéritif"
;; ⇒ nil
(println (format "*url* is now %s" *url*))
;; outputs "*url* is now http://en.wikipedia.org/wiki/Margarita"
;; ⇒ nil
</code></pre><p>As you can see, var scoping in different threads did not modify the var's value in the thread it was
originally defined in (its <em>root binding</em>). In real-world cases, for example, it means that a multi-threaded
Web crawler can store some crawling state specific to a particular thread in a var and not
modify its initial (global) value.</p><h4 id="how-to-alter-var-root">How to Alter Var Root</h4><p>Sometimes, however, modifying the root binding is necessary. This is done via <code>clojure.core/alter-var-root</code>
which takes a var (not its value) and a function that takes the old var value and returns a new one:</p><pre><code class="clojure">*url*
;; ⇒ "http://en.wikipedia.org/wiki/Margarita"
(.start (Thread. (fn []
(alter-var-root (var user/*url*) (fn [_] "http://en.wikipedia.org/wiki/Apéritif"))
(println (format "*url* is now %s" *url*)))))
;; outputs "*url* is now http://en.wikipedia.org/wiki/Apéritif"
;; ⇒ nil
*url*
;; ⇒ "http://en.wikipedia.org/wiki/Apéritif"
</code></pre><p><code>clojure.core/var</code> is used to locate the var (<code>user/*url*</code> in our example executed in the REPL). Note that it
finds the var itself (the reference, the "box"), not its value (what the var evalutes to).</p><p>In the example above the function we use to alter var root ignores the current value and simply returns a
predefined string:</p><pre><code class="clojure">(fn [_] "http://en.wikipedia.org/wiki/Apéritif")
</code></pre><p>Such functions are common enough for <code>clojure.core</code> to provide a convenience higher-order function called
<code>clojure.core/constantly</code>. It takes a value and returns a function that, when executed, ignores all its parameters
and returns that value. So, the function above would be more idiomatically written as</p><pre><code class="clojure">*url*
;; ⇒ "http://en.wikipedia.org/wiki/Margarita"
(.start (Thread. (fn []
(alter-var-root (var user/*url*) (constantly "http://en.wikipedia.org/wiki/Apéritif"))
(println (format "*url* is now %s" *url*)))))
;; outputs "*url* is now http://en.wikipedia.org/wiki/Apéritif"
;; ⇒ nil
*url*
;; ⇒ "http://en.wikipedia.org/wiki/Apéritif"
</code></pre><p>When is <code>alter-var-root</code> used in real world scenarios? Some Clojure data store and API clients stores active connection
in a var, so initial connection requires root binding modification.</p><h4 id="summary-and-use-cases-3">Summary and Use Cases</h4><p>To summarize: vars can have dynamic scope. They have a root binding and can have thread-local bindings as well.
As such, vars are good for storing pieces of program state that vary between threads but cannot
be stored in a function local. <code>alter-var-root</code> is used to alter root binding of a var. It is done
the functional way: by providing a function that takes the old var value and returns a new one.</p><p>To alter var root to a specific known value, use <code>clojure.core/constantly</code>.</p><h2 id="dereferencing">Dereferencing</h2><p>Earlier sections demonstrated the concept of <em>dereferencing</em>. Dereferencing means retrieving the current
value of a reference (an atom, an agent, a ref, etc). To dereference a Clojure reference, use
<code>clojure.core/deref</code> or the <code>@reference</code> reader macro:</p><pre><code class="clojure">(let [xs (atom [])]
@xs)
;; ⇒ []
</code></pre><p>Besides atoms, agents, and refs, Clojure has several other concurrency-oriented data structures
that can be dereferenced: delays, futures, and promises. They will be covered later in this
guide.</p><h3 id="dereferencing-support-for-data-types-implemented-in-java">Dereferencing Support For Data Types Implemented In Java</h3><p>It is possible to make custom data types implemented in Java support dereferencing by
making them implement the <code>clojure.lang.</code> interface:</p><pre><code class="java">package clojure.lang;
public interface IDeref{
Object deref();
}
</code></pre><p>This can be done to make data types implemented in Java look and feel more like built-in
Clojure data types, or make it possible to pass said types to a function that expects
its arguments to be dereferenceable.</p><h2 id="delays">Delays</h2><p>In Clojure, a <em>delay</em> is a data structure that is evaluated the first time it is dereferenced.
Subsequent dereferencing will use the cached value. Delays are instantiated with the <code>clojure.core/delay</code>
function.</p><p>In the following example a delay is used to calculate a timestamp that is later used
as a cached value:</p><pre><code class="clojure">(def d (delay (System/currentTimeMillis)))
;; ⇒ #'user/d
d
;; ⇒ #&lt;Delay@21ed22af: :pending&gt;
;; dereferencing causes the value to be realized, it happens only once
@d
;; ⇒ 1350997814621
@d
;; ⇒ 1350997814621
@d
;; ⇒ 1350997814621
</code></pre><p><code>clojure.core/realized?</code> can be used to check whether a delay instance has been realized
or not:</p><pre><code class="clojure">(def d (delay (System/currentTimeMillis)))
;; ⇒ #'user/d
(realized? d)
;; ⇒ false
@d
;; ⇒ 1350997967984
(realized? d)
;; ⇒ true
</code></pre><h2 id="futures">Futures</h2><p>A Clojure future evaluates a piece of code in another thread. To instantiate a future,
use <code>clojure.core/future</code>. The <code>future</code> function will return immediately (it never blocks
the current thread). To obtain the result of computation, dereference the future:</p><pre><code class="clojure">(def ft (future (+ 1 2 3 4 5 6)))
;; ⇒ #'user/ft
ft
;; ⇒ #&lt;core$future_call$reify__6110@effa25e: 21&gt;
@ft
;; ⇒ 21
</code></pre><p>Dereferencing a future blocks the current thread. Because some operations may take
a very long time or get blocked forever, futures support a timeout specified
when you dereference them:</p><pre><code class="clojure">;; will block the current thread for 10 seconds, returns :completed
(def ft (future (Thread/sleep 10000) :completed))
;; ⇒ #'user/ft
(deref ft 2000 :timed-out)
;; ⇒ :timed-out
</code></pre><p>Subsequent access to futures using <code>deref</code> will use the cached value, just like it
does for delays.</p><p>Just like delays, it is possible to check whether a future is realized or not
with <code>clojure.core/realized?</code>:</p><pre><code class="clojure">(def ft (future (reduce + (range 0 10000))))
;; ⇒ #'user/ft
(realized? ft)
;; ⇒ true
@ft
;; ⇒ 49995000
</code></pre><p>Clojure futures are evaluated in an unbounded, cached thread pool that is also used by agents
(updated via <code>clojure.core/send-off</code>). This works well in many cases but may result in
exhaustion of the heap or thrashing if too many futures are created.</p><p>Finally, Clojure futures implement <code>java.util.concurrent.Future</code> and can be used with Java APIs
that accept them.</p><h2 id="promises">Promises</h2><p>Promises are yet another take on asynchronously realized values. They are similar to futures in
certain ways:</p><ul><li>Can be dereferenced with a timeout</li><li>Caches the realized value</li><li>Supported by <code>clojure.core/realized?</code></li></ul><p>However, promises are realized not by evaluating a piece of code but by calling <code>clojure.core/deliver</code>
on a promise along with a value:</p><pre><code class="clojure">;; promises have no code body (no code to evaluate)
(def p (promise))
;; ⇒ #'user/p
p
;; ⇒ #&lt;core$promise$reify__6153@306a0a21: :pending&gt;
(realized? p)
;; ⇒ false
;; delivering a promise makes it realized
(deliver p {:result 42})
;; ⇒ #&lt;core$promise$reify__6153@306a0a21: {:result 42}&gt;
(realized? p)
;; ⇒ true
@p
;; ⇒ {:result 42}
</code></pre><p>Promises combine many of the benefits of callback-oriented asynchronous programming
and the simpler blocking function calls model provided by dereferencing.</p><h2 id="watches-and-validators">Watches and Validators</h2><p><em>TBD</em></p><h2 id="using-intrinsic-locks-synchronized-in-clojure">Using Intrinsic Locks ("synchronized") in Clojure</h2><h3 id="explicit-locking">Explicit Locking</h3><p>Every object on the JVM has an <em>intrinsic lock</em> (also referred to as <em>monitor lock</em>
or simply <em>monitor</em>). By convention, a thread that needs to modify a field of a
mutable object has to acquire the object's intrinsic lock and then release it.
As long as a thread owns an intrinsic lock, no other thread can acquire the same lock.</p><p>In Clojure, explicit synchronization like this is rarely necessary but may be
needed for interoperability with Java code. When you need to execute a piece
of code while holding an intrinsic lock of a mutable object, use
the <code>clojure.core/locking</code> macro:</p><pre><code class="clojure">(let [l (java.util.ArrayList.)]
(locking l
(.add l 10))
l)
;; ⇒ #&lt;ArrayList [10]&gt;
</code></pre><p>Note that for immutable Clojure data structures, explicit locking is effectively
not necessary.</p><h3 id="synchronization-on-clojure-record-fields">Synchronization on Clojure Record Fields</h3><p><em>TBD</em></p><h2 id="reducers-clojure-15">Reducers (Clojure 1.5+)</h2><p><em>TBD</em></p><h2 id="javautilconcurrent">java.util.concurrent</h2><h3 id="overview-2">Overview</h3><p><code>java.util.concurrent</code> (sometimes abbreviated as <code>j.u.c.</code>) is a group of
<em>concurrency utilities</em> in the JDK. Originally introduced in JDK 5 in 2004,
they are developed and maintained by some of the experts in concurrency.
<code>j.u.c.</code> is a mature library that has been heavily battle tested for
almost a decade.</p><p>While Clojure provides a whole toolbelt of concurrency features of its own,
in certain cases the best solution is to use an existing <code>j.u.c.</code> class
or even build a new abstraction on top of <code>j.u.c.</code> building blocks.</p><p><code>j.u.c.</code> consists of multiple parts that cover common concurrent programming
patterns and use cases: from thread pools (a.k.a. <em>executors</em>) to synchronization
classes, to atomic variables, to concurrent collections, to the Fork/Join
framework.</p><h3 id="executors-thread-pools">Executors (Thread Pools)</h3><h4 id="overview-3">Overview</h4><p>The Executor interface standardizes invocation, scheduling, execution, and control of asynchronous tasks.
Those tasks can be executed in the calling thread, in newly created threads, or (mostly typically)
in a thread pool. Thread pools also can have different implementations: for example,
be fixed size or growing dynamically, using different error handling strategies and so on.</p><p>Executors are most often instantiated using static methods of the <code>java.util.concurrent.Executors</code> class. To submit an operation to the pool, use the <code>ExecutorService#submit</code> method.</p><pre><code class="clojure">(import '[java.util.concurrent Executors ExecutorService Callable])
(let [^ExecutorService pool (Executors/newFixedThreadPool 16)
^Callable clbl (cast Callable (fn []
(reduce + (range 0 10000))))]
(.submit pool clbl))
;; ⇒ #&lt;FutureTask java.util.concurrent.FutureTask@19ca276f&gt;
</code></pre><p>In the example above, we create a new fixed size thread pool with 16 threads
and submit a Clojure function for execution. Clojure functions <a href="../interop/index.html#clojure_functions_implement_runnable_and_callable">implement Runnable and Callable</a>
interfaces and can be submitted for execution, however, because <code>ExecutorService#submit</code>
is an overloaded method, to avoid reflection warnings, we cast the function
to <code>java.util.concurrent.Callable</code>.</p><h4 id="javautilconcurrentfuture">java.util.concurrent.Future</h4><p><code>Executor#submit</code> will return an instance of <code>java.util.concurrent.Future</code>. It is much like Clojure
futures but cannot be dereferenced. To get the result, use the <code>j.u.c.Future#get</code> method:</p><pre><code class="clojure">(import '[java.util.concurrent Executors ExecutorService Callable])
(let [^ExecutorService pool (Executors/newFixedThreadPool 16)
^Callable clbl (cast Callable (fn []
(reduce + (range 0 10000))))
task (.submit pool clbl)]
(.get task))
;; ⇒ 49995000
</code></pre><h4 id="scheduled-executors">Scheduled Executors</h4><p><em>TBD</em></p><h3 id="countdown-latches">Countdown Latches</h3><p><em>Countdown latch</em> is a thread synchronization data structure. More specifically, it handles
on group of concurrent workflows: "block the current thread until N other threads are
done with their work". For example, "make a POST request to N URLs and continue when all N operations
succeeded or failed".</p><p>Countdown latches are instances of <code>java.util.concurrent.CountDownLatch</code> and instantiated with
a positive integer:</p><pre><code class="clojure">(import java.util.concurrent.CountDownLatch)
(CountDownLatch. n)
</code></pre><p>When the <code>CountDownLatch#await</code> method is executed, the calling thread blocks until the counter
gets to 0. Invoking the <code>CountDownLatch#countDown</code> method decreases the counter by 1. Count down
operations, of course, are supposed to be performed in other threads.</p><p>An example to demonstrate:</p><pre><code class="clojure">(let [cnt (atom [])
n 5
latch (java.util.concurrent.CountDownLatch. n)]
(doseq [i (range 0 n)]
(.start (Thread. (fn []
(swap! cnt conj i)
(.countDown latch)))))
(.await latch)
@cnt)
;; note the ordering: starting N threads in parallel leads to
;; non-deterministic thread interleaving
;; ⇒ [0 1 2 4 3]
</code></pre><p>In the example above, we start multiple threads and block the current thread until all other
threads are done. In this example, those other threads simply add an integer to a vector
stored in an atom. More realistic scenarios will contact external services, the file system,
perform some computation and so on.</p><p>Because when threads are executed concurrently (or in parallel), the order of their execution is not
guaranteed, we see 4 being added to the vector before 3 in the result.</p><p>Countdown latches are commonly used with initial value of 1 to "block and wait until this operation in
a different thread is done".</p><h3 id="concurrent-collections">Concurrent Collections</h3><p>Most of the Java collections are mutable and were not designed for concurrency. <code>java.util.concurrent</code> includes a number of collections that
are thread safe and can be used for passing data structures between threads.</p><h3 id="atomic-variables">Atomic Variables</h3><p>The <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html">java.util.concurrent.atomic</a> package provides
a number of data structures that support lock-free thread-safe programming on a single variable (identity). They support
conditional atomic update operation (<em>compared-and-swap</em> aka <em>CAS</em>).</p><p>Some of the more popular atomic types in the <code>j.u.c.atomic</code> package are <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html">AtomicBoolean</a>,
<a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html">AtomicLong</a> and <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicReference.html">AtomicReference</a>.</p><p>Atomic references are pretty well covered in Clojure with atoms but ocassionally may be used by
other libraries. An example to demonstrate how to use an atomic long for a thread-safe counter:</p><pre><code class="clojure">(let [l (AtomicLong.)]
(dotimes [i 50]
(.start (Thread. (fn []
(.incrementAndGet l)))))
(.get l))
;; ⇒ 49
</code></pre><h3 id="forkjoin-framework">Fork/Join Framework</h3><p><em>TBD</em></p><h2 id="other-approaches-to-concurrency">Other Approaches to Concurrency</h2><p>There are also other approaches to concurrency that neither Clojure nor Java cover. The growing
adoption of <em>message passing</em> concurrency (the <a href="http://en.wikipedia.org/wiki/Actor_model">Actor model</a> and <a href="http://en.wikipedia.org/wiki/Communicating_Sequential_Processes">CSP</a>)
lead to the creation of several JVM-based frameworks for message passing. Some of the most popular ones
include:</p><ul><li><a href="http://akka.io">Akka</a></li><li><a href="http://code.google.com/p/jetlang/">Jetlang</a></li><li><a href="http://lmax-exchange.github.com/disruptor/">LMAX Disruptor</a></li></ul><p>Akka's Java API can be used from Clojure either directly or via a library called <a href="https://github.com/gaverhae/okku">Okku</a>.</p><p>In LMAX Disruptor, event instances passed around are assumed to be mutable, so the framework is of limited use with Clojure.</p><h2 id="runtime-parallelism">Runtime Parallelism</h2><p>Clojure was designed to be a hosted language. Its primary target, the
JVM, provides runtime parallelism support. JVM threads map 1:1 to
kernel threads. Those will be executed in parallel given that enough
cores are available for OS scheduler to use.</p><p>In Clojure, many concurrency features are built on top of JVM threads
and thus benefit from runtime parallelism if the program is running on
a multi-core machine.</p><h2 id="books">Books</h2><p>Concurrency is a broad topic and it would be silly to think that we
can cover it well in just one guide. To get a better understanding of
the subject, one can refer to a few excellent books:</p><ul><li><a href="http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601">Java Concurrency in Practice</a> by Brian Goetz et al. is a true classic.</li><li><a href="http://pragprog.com/book/vspcon/programming-concurrency-on-the-jvm">Programming Concurrency on the JVM</a> demonstrates a range of concurrency features in several JVM languages.</li></ul><h2 id="wrapping-up">Wrapping Up</h2><p>One of Clojure design goals was to make concurrent programming easier.</p><p>The key design decision was making Clojure data structures immutable
(persistent) and separating the concepts of <em>identity</em> (references)
and <em>value</em>. Immutable values eliminate many concurrency hazards, and
ultimately make it easier for developers to reason about their
programs.</p><p>Atoms are arguably the most commonly used reference type when working
with concurrency (vars are used much more often but not for their
concurrency semantics). Software Transactional Memory is a more
specialized feature and has certain limitations (e.g., I/O operations
must not be performed inside transactions). Finally, agents, futures,
and promises provide an array of tools for working with asynchronous
operations.</p><p>Concurrency is a hard fundamental problem. There is no single "best"
solution or approach to it. On the JVM, Clojure offers several
concurrency-related features of its own but also provides easy access
to the <code>java.util.concurrent</code> primitives and libraries such as
<a href="http://akka.io/">Akka</a> or
<a href="http://code.google.com/p/jetlang/">Jetlang</a>.</p><h2 id="contributors">Contributors</h2><p>Michael Klishin <a href="mailto:michael@defprotocol.org">michael@defprotocol.org</a>, 2012 (original author)</p>
<div id="prev-next">
<a href="../polymorphism/index.html">&laquo; Polymorphism in Clojure: Protocols and Multimethods</a>
||
<a href="../glossary/index.html">Clojure Terminology Guide &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../functions/index.html">Functions in Clojure</a></li>
<li><a href="../laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,745 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Overview of clojure.core, the standard Clojure library</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/core_overview/" />
<meta property="og:title" content="Overview of clojure.core, the standard Clojure library" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/core_overview/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Overview of clojure.core, the standard Clojure library</h2>
</div>
<p>This guide covers:</p><ul><li>Key functions of <code>clojure.core</code></li><li>Key macros of <code>clojure.core</code></li><li>Key vars of <code>clojure.core</code></li><li>Essential special forms</li></ul><p>This guide is <strong>by no means comprehensive</strong> and does not try to explain each function/macro/form in depth. It is an overview,
the goal is to briefly explain the purpose of each item and provide links to other articles with more information.</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5.</p><h2 id="binding">Binding</h2><p><a id="let_desc"></a></p><h3 id="let">let</h3><pre><code class="clojure">(let [bindings*] exprs*)
</code></pre><p><code>let</code> takes a vector of symbol value pairs followed by a variable number of expressions.</p><p><code>let</code> allows binding of locals (roughly equivalent to variables in many other languages) and defines an explicit scope for those bindings.</p><p>The body of a <code>let</code> statement also provides an implicit <code>do</code> that allows for multiple statements in the body of <code>let</code>.</p><p>A basic example:</p><pre><code class="klipse-clojure nohighlight">(let [x 1 y 2]
(println x y))
</code></pre><p>Let can be nested, and the scope is lexically determined. This means that a binding's value is determined by the nearest binding form for that symbol.</p><p>This example basically demonstrates the lexical scoping of the let form.</p><pre><code class="klipse-clojure nohighlight">(let [x 1]
(println x) ; prints 1
(let [x 2]
(println x))) ; prints 2
</code></pre><p>Let bindings are immutable and can be destructured.</p><p>See: Sections about destructuring in
<a href="../../tutorials/introduction/index.html#destructuring">Introduction</a> and
<a href="../functions/index.html#destructuring-of-function-arguments">Functions</a>
pages.</p><p><a id="def_desc"></a></p><h3 id="def">def</h3><pre><code class="clojure">(def symbol doc-string? init?)
</code></pre><p><code>def</code> takes a symbol and an optional init value.</p><p>If an init value is supplied, the root binding of the var is assigned to that value. Redefining a var with an init value will re-assign the root binding.</p><p>A root binding is a value that is shared across all threads.</p><p>The <code>let</code> form is the preferred method of creating local bindings. It is strongly suggested to prefer it where possible, and never use <code>def</code> within another form.</p><pre><code class="clojure">;; TBD - reference to var documentation, basic example
;; TBD - metadata
</code></pre><p><a id="declare_desc"></a></p><h3 id="declare">declare</h3><pre><code class="clojure">([&amp; names])
</code></pre><p><code>declare</code> takes a variable number of symbols.</p><p><code>declare</code> provides a simple way of creating 'forward declarations'. <code>declare</code> defs the supplied symbols with no init values. This allows for referencing of a var before it has been supplied a value.</p><p>There are much better methods of value-based dispatch or code architecture in general, but this presents a simple situation forward declarations would be necessary.</p><pre><code class="klipse-clojure nohighlight">(declare func&lt;10 func&lt;20)
;; without declare you will receive an error similar to:
;; "Unable to resolve symbol: func10 in this context"
(defn func&lt;10 [x]
(cond
(&lt; x 10) (func&lt;10 (inc x))
(&lt; x 20) (func&lt;20 x)
:else "too far!"))
(defn func&lt;20 [x]
(cond
(&lt; x 10) (func&lt;10 x)
(&lt; x 20) "More than 10, less than 20"
:else "too far!"))
</code></pre><p>No matter which order you put func&lt;10 and func&lt;20 in, there will be a reference to a var that does not yet exist when the compiler does the initial evaluation of top-level forms.</p><p><code>declare</code> defines the var with no binding so that the the var exists when it is referenced later in the code.</p><p><a id="defn_desc"></a></p><h3 id="defn">defn</h3><pre><code class="clojure">([name doc-string? attr-map? [params*] prepost-map? body] [name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?])
</code></pre><p><code>defn</code> takes a symbol, an optional doc string, an optional meta-data
map, a vector of arguments and a variable number of expressions.</p><p><code>defn</code> is the primary way of defining functions. It allows for
convenient definition of metadata about its argslist and documentation
(docstrings). <code>defn</code> inherently allows for quick documentation of
functions that can be retrieved with <code>doc</code>. This feature should be
used almost universally.</p><p>Without <code>defn</code>, a var would be directly bound to a function definition
and explicit metadata about the doc string and argslits would be added
manually.</p><pre><code class="clojure">(def func (fn [x] x))
;; same as:
(defn func [x]
x)
;; with metadata added by defn
(def ^{:doc "documentation!"} ^{:arglists '([x])} func (fn [x] x))
;;same as
(defn func
"documentation!"
[x]
x)
</code></pre><pre><code class="clojure">;; TBD - link to doc and metadata
</code></pre><h2 id="branching">Branching</h2><p><a id="if_desc"></a></p><h3 id="if">if</h3><pre><code class="clojure">(if test then else?)
</code></pre><p><code>if</code> takes 2 expressions, and an optional third.</p><p><code>if</code> is the primary method of conditional execution and other conditionals are built upon <code>if</code>.</p><p>If the return value of the first expression is anything except nil or false, the second expression is evaluated and the result returned..</p><p>If a third expression is provided, when the first expression returns nil or false the third expression is evaluated and returned.</p><pre><code class="klipse-clojure nohighlight">(if 0 "second") ; 0 is a 'true' value. Only false or nil are 'false'
</code></pre><pre><code class="klipse-clojure nohighlight">(if nil "second" "third")
</code></pre><pre><code class="klipse-clojure nohighlight">(if (&lt; 10 9) "second" "third") ; (&lt; 9 10) returns false
</code></pre><pre><code class="klipse-clojure nohighlight">(if (seq '()) "second") ; seq returns nil for an empty sequence
</code></pre><pre><code class="klipse-clojure nohighlight">(if (nil? (= 1 2)) "second" "third") ; differentiate between nil and false if needed
</code></pre><p><a id="when_desc"></a></p><h3 id="when">when</h3><pre><code class="clojure">([test &amp; body])
</code></pre><p><code>when</code> takes 2 expressions.</p><p><code>when</code> provides an implicit do form that is evaluated if an expression returns true, otherwise nil is returned. <code>when</code> does not provide an 'else'.</p><pre><code class="klipse-clojure nohighlight">(when (= 1 2) (print "hey") 10)
</code></pre><pre><code class="klipse-clojure nohighlight">(when (&lt; 10 11) (print "hey") 10)
</code></pre><h3 id="for">for</h3><p>See: <a href="index.html#for_desc">for</a></p><h3 id="doseq">doseq</h3><p>See: <a href="index.html#doseq_desc">doseq</a></p><h2 id="looping">Looping</h2><p><a id="recur_desc"></a></p><h3 id="recur">recur</h3><pre><code class="clojure">(recur exprs*)
</code></pre><p><code>recur</code> allows for self-recursion without consuming stack space proportional to the number of recursive calls made. Due to the lack of tail-call optimization on the JVM currently, this is the only method of recursion that does not consume excess stack space.</p><p><code>recur</code> takes a number of arguments identical to the point of recursion. <code>recur</code> will evaluate those arguments, rebind them at the point of recursion and resume execution at that point.</p><p>The point of recursion is the nearest <code>fn</code> or <code>loop</code> form determined lexically.</p><p><code>recur</code> must be in the tail position of the recursion point expression. The tail position is the point in the expression where a return value would otherwise be determined and.</p><p><code>recur</code> does not bind <code>&amp;</code> in variadic functions and in these situations an empty seq must be passed by <code>recur</code>.</p><pre><code class="klipse-clojure nohighlight">(defn count-up
[result x y]
(if (= x y)
result
(recur (conj result x) (inc x) y)))
(count-up [] 0 10)
</code></pre><p>Example: getting factorial of a positive integer:</p><pre><code class="klipse-clojure nohighlight">(defn factorial
([n]
(factorial n 1))
([n acc]
(if (zero? n)
acc
(recur (dec n) (* n acc)))))
(factorial 10)
;; ⇒ 3628800
</code></pre><p>TBD: more examples</p><p><a id="loop_desc"></a></p><h3 id="loop">loop</h3><pre><code class="clojure">(loop [bindings*] exprs*)
</code></pre><p><code>loop</code> takes a vector of symbol value pairs followed by a variable number of expressions.</p><p><code>loop</code> establishes a recursion point for a <code>recur</code> expression inside its body. <code>loop</code> provides an implicit <code>let</code> for bindings.</p><p>The implicit <code>let</code> that <code>loop</code> provides binds each symbol to the init-expression. <code>recur</code> then binds new values when returning the execution point to <code>loop</code>.</p><pre><code class="klipse-clojure nohighlight">(defn count-up
[start total]
(loop [result []
x start
y total]
(if (= x y)
result
(recur (conj result x) (inc x) y))))
(count-up 0 10)
;; ⇒ [0 1 2 3 4 5 6 7 8 9]
</code></pre><p>Example: getting factorial of a positive integer:</p><pre><code class="klipse-clojure nohighlight">(defn factorial
[n]
(loop [n n
acc 1]
(if (zero? n)
acc
(recur (dec n) (* acc n)))))
(factorial 10)
;; ⇒ 3628800
</code></pre><p>TBD: more examples</p><p><a id="trampoline_desc"></a></p><h3 id="trampoline">trampoline</h3><pre><code class="clojure">([f])
([f &amp; args])
</code></pre><p><code>trampoline</code> takes a function and a variable number of arguments to pass to that function.</p><p><code>trampoline</code> allows for mutual recursion without consuming stack space proportional to the number of recursive calls made.</p><p>If the return value of that function is a function, <code>trampoline</code> calls that function with no arguments. If the return value is not a function, <code>trampoline</code> simply returns that value.</p><p>Since <code>trampoline</code> calls the returned functions with no arguments, you must supply an anonymous function that takes no arguments and calls the function you wish to recur to. This is usually done with anonymous function literals <code>#()</code></p><pre><code class="klipse-clojure nohighlight">(declare count-up1 count-up2) ;; see `declare` for why this is needed
(defn count-up1
[result start total]
(if (= start total)
result
#(count-up2 (conj result start) (inc start) total))) ;; returns an anonymous function
(defn count-up2 [result start total]
(if (= start total)
result
#(count-up1 (conj result start) (inc start) total))) ;; returns an anonymous function
#_(trampoline count-up1 [] 0 10)
;; ⇒ [0 1 2 3 4 5 6 7 8 9]
</code></pre><p>TBD: a trivial example that would not be easily solved with self-recursion</p><p><a id="for_desc"></a></p><h3 id="for-1">for</h3><pre><code class="clojure">([seq-exprs body-expr])
</code></pre><p><code>for</code> takes a vector of pairs of [binding collection].</p><p><code>for</code> allows for list comprehensions. <code>for</code> assigns each sequential value in the collection to the binding form and evaluates them rightmost first. The results are returned in a lazy sequence.</p><p><code>for</code> allows for explicit let, when and while through use of ":let []" ":when (expression)" ":while (expression)" in the binding vector.</p><pre><code class="klipse-clojure nohighlight">(for [x [1 2 3] y [4 5 6]]
[x y])
;; ⇒ ([1 4] [1 5] [1 6] [2 4] [2 5] [2 6] [3 4] [3 5] [3 6])
</code></pre><p>:when only evaluates the body when a true value is returned by the expression provided</p><pre><code class="klipse-clojure nohighlight">(for [x [1 2 3] y [4 5 6]
:when (and
(even? x)
(odd? y))]
[x y])
;; ⇒ ([2 5])
</code></pre><p>:while evaluates the body until a non-true value is reached. Note that the rightmost collection is fully bound to y before a non-true value of (&lt; x 2) is reached. This demonstrates the order of the comprehension.</p><pre><code class="klipse-clojure nohighlight">(for [x [1 2 3] y [4 5 6]
:while (&lt; x 2)]
[x y])
;; ⇒ ([1 4] [1 5] [1 6])
</code></pre><p><a id="doseq_desc"></a></p><h3 id="doseq-1">doseq</h3><pre><code class="clojure">([seq-exprs &amp; body])
</code></pre><p><code>doseq</code> takes a vector of pairs of [binding collection].</p><p><code>doseq</code> is similar to <code>for</code> except it does not return a sequence of results. <code>doseq</code> is generally intended for execution of side-effects in the body, and thusly returns nil.</p><p><code>doseq</code> supports the same bindings as for - :let :when :while. For examples of these, see for.</p><pre><code class="klipse-clojure nohighlight">(doseq [x [1 2 3] y [4 5 6]]
(println [x y]))
;; [1 4][1 5][1 6][2 4][2 5][2 6][3 4][3 5][3 6]
;; ⇒ nil
</code></pre><p><a id="iterate_desc"></a></p><h3 id="iterate">iterate</h3><pre><code class="clojure">([f x])
</code></pre><p><code>iterate</code> takes a function and an argument to the function.</p><p>A lazy sequence is returned consisting of the argument then each subsequent entry is the function evaluated with the previous entry in the lazy sequence.</p><pre><code class="clojure">TBD: Examples
</code></pre><p>TBD: Simple image accompaniment.</p><p><a id="reduce_desc"></a></p><h3 id="reduce">reduce</h3><pre><code class="clojure">([f coll])
([f val coll])
</code></pre><p><code>reduce</code> takes a function, an optional initial value and a collection.</p><p><code>reduce</code> takes the first item of the collection and either the second
item of the collection or the provided initial value, then evaluates
the function with those arguments. The function is then evaluated with
that result and the next item in the collection. This is repeated
until the collection is exhausted and the value of the final function
call is returned.</p><pre><code class="clojure">TBD: examples
</code></pre><p>TBD: Simple image accompaniment.</p><p><a id="reductions_desc"></a></p><h3 id="reductions">reductions</h3><pre><code class="clojure">([f coll])
([f val coll])
</code></pre><p><code>reductions</code> takes a function, an optional initial value and a collection.</p><p><code>reductions</code> returns a lazy sequence consisting of the first item in
the collection, or the provided initial value followed by the result
of the function evaluated with the previous result and the next item
in the collection.</p><pre><code class="clojure">TBD: examples
</code></pre><p>TBD: Simple image accompaniment.</p><p><a id="map_desc"></a></p><h3 id="map">map</h3><pre><code class="clojure">([f coll])
([f c1 c2])
([f c1 c2 c3])
([f c1 c2 c3 &amp; colls])
</code></pre><p><code>map</code> takes a function and one or more collections. <code>map</code> passes an
item from each collection, in order, to the function and returns a
lazy sequence of the results.</p><p>The function provided to <code>map</code> must support an arity matching the
number of collections passed. Due to this, when using more than one
collection, map stops processing items when any collection runs out of
items.</p><pre><code class="clojure">TBD: Examples
</code></pre><p>TBD: Simple image accompaniment.</p><h2 id="collection-and-sequence-modification">Collection and Sequence Modification</h2><p><a id="conj_desc"></a></p><h3 id="conj">conj</h3><pre><code class="clojure">([coll x])
([coll x &amp; xs])
</code></pre><p><code>conj</code> takes a collection and a variable number of arguments.</p><p><code>conj</code> is short for "conjoin". As the name implies, <code>conj</code> returns the
collection with those arguments added.</p><p>Adding items to a collection occurs at different places depending on
the concrete type of collection.</p><p>List addition occurs at the beginning of the list. This is because
accessing the head of the list is a constant time operation, and
accessing the tail requires traversal of the entire list.</p><pre><code class="clojure">(conj '(1 2) 3)
;; ⇒ (3 1 2)
</code></pre><p>Vectors have constant time access across the entire data
structure. `'conj' thusly appends to the end of a vector.</p><pre><code class="klipse-clojure nohighlight">(conj [1 2] 3)
;; ⇒ [1 2 3]
</code></pre><p>Maps do not have guaranteed ordering, so the location that items are
added is irrelevant. <code>conj</code> requires vectors of [key value] pairs to
be added to the map.</p><pre><code class="klipse-clojure nohighlight">(conj {:a 1 :b 2 :c 3} [:d 4])
;; ⇒ {:d 4, :a 1, :c 3, :b 2}
</code></pre><pre><code class="klipse-clojure nohighlight">(conj {:cats 1 :dogs 2} [:ants 400] [:giraffes 13])
;; ⇒ {:giraffes 13, :ants 400, :cats 1, :dogs 2}
</code></pre><p>Sets also do not have guaranteed ordering. <code>conj</code> returns a set with
the item added. As the concept of sets implies, added items will not
duplicate equivalent items if they are present in the set.</p><pre><code class="klipse-clojure nohighlight">(conj #{1 4} 5)
;; ⇒ #{1 4 5}
</code></pre><pre><code class="klipse-clojure nohighlight">(conj #{:a :b :c} :b :c :d :e)
;; ⇒ #{:a :c :b :d :e}
</code></pre><p><a id="empty_desc"></a></p><h3 id="empty">empty</h3><pre><code class="clojure">([coll])
</code></pre><p><code>empty</code> takes a collection</p><p><code>empty</code> returns an empty collection of the same type as the collection
provided.</p><pre><code class="klipse-clojure nohighlight">(empty [1 2 3])
;; ⇒ []
</code></pre><pre><code class="klipse-clojure nohighlight">(empty {:a 1 :b 2 :c 3})
;; ⇒ {}
</code></pre><p><a id="assoc_desc"></a></p><h3 id="assoc">assoc</h3><pre><code class="clojure">([map key val])
([map key val &amp; kvs])
</code></pre><p><code>assoc</code> takes a key and a value and returns a collection of the same
type as the supplied collection with the key mapped to the new value.</p><p><code>assoc</code> is similar to get in how it works with maps, records or
vectors. When applied to a map or record, the same type is returned
with the key/value pairs added or modified. When applied to a vector,
a vector is returned with the key acting as an index and the index
being replaced by the value.</p><p>Since maps and records can not contain multiple equivalent keys,
supplying <code>assoc</code> with a key/value that exists in the one will cause
<code>assoc</code> to return modify the key at that value in the result and not
duplicate the key.</p><pre><code class="klipse-clojure nohighlight">(assoc {:a 1} :b 2)
;; ⇒ {:b 2, :a 1}
</code></pre><pre><code class="klipse-clojure nohighlight">(assoc {:a 1 :b 45 :c 3} :b 2)
;; ⇒ {:a 1, :c 3, :b 2}
</code></pre><pre><code class="klipse-clojure nohighlight">(defrecord Hand [index middle ring pinky thumb])
(assoc (Hand. 3 4 3.5 2 2) :index 3.75)
;; ⇒ #user.Hand{:index 3.75, :middle 4, :ring 3.5, :pinky 2, :thumb 2}
</code></pre><p>When using <code>assoc</code> with a vector, the key is
the index and the value is the value to assign to that index in the
returned vector. The key must be &lt;= (count vector) or a
"IndexOutOfBoundsException" will occur. <code>assoc</code> can not be used to add
an item to a vector.</p><pre><code class="klipse-clojure nohighlight">(assoc [1 2 76] 2 3) ;= [1 2 3]
</code></pre><pre><code class="klipse-clojure nohighlight">;; index 5 does not exist. valid indexes for this vector are: 0, 1, 2
(assoc [1 2 3] 5 6)
;; IndexOutOfBoundsException clojure.lang.PersistentVector.assocN (PersistentVector.java:136)
</code></pre><p><a id="dissoc_desc"></a></p><h3 id="dissoc">dissoc</h3><pre><code class="clojure">([map])
([map key])
([map key &amp; ks])
</code></pre><p><code>dissoc</code> takes a map and a variable number of keys.</p><p><code>dissoc</code> returns a map with the supplied keys, and subsequently their
values, removed. Unlike <code>assoc</code>, <code>dissoc</code> does not work on
vectors. When a record is provided, <code>dissoc</code> returns a map. For
similar functionality with vectors, see <code>subvec</code> and <code>concat</code>.</p><pre><code class="klipse-clojure nohighlight">(dissoc {:a 1 :b 2 :c 3} :b)
;; ⇒ {:a 1, :c 3}
</code></pre><pre><code class="klipse-clojure nohighlight">(dissoc {:a 1 :b 14 :c 390 :d 75 :e 2 :f 51} :b :c :e)
;; ⇒ {:a 1, :f 51, :d 75}
</code></pre><pre><code class="klipse-clojure nohighlight">;; note that a map is returned, not a record.
(defrecord Hand [index middle ring pinky thumb])
;; always be careful with the bandsaw!
(dissoc (Hand. 3 4 3.5 2 2) :ring)
;; ⇒ {:index 3, :middle 4, :pinky 2, :thumb 2}
</code></pre><h2 id="information-about-a-collection-or-sequence">Information about a Collection or Sequence</h2><p><a id="count_desc"></a></p><h3 id="count">count</h3><pre><code class="clojure">([coll])
</code></pre><p><code>count</code> takes a collection.</p><p>Returns a count of the number of items in a collection. An argument of nil returns 0.</p><pre><code class="klipse-clojure nohighlight">(count "Hello")
;; ⇒ 5
</code></pre><pre><code class="klipse-clojure nohighlight">(count [1 2 3 4 5 6 7])
;; ⇒ 7
</code></pre><pre><code class="klipse-clojure nohighlight">(count nil)
;; ⇒ 0
</code></pre><p>Note that count does not return in constant time for all
collections. This can be determined with <code>counted?</code>. Keep in mind
that lazy sequences must be realized to get a count of the items. This
is often not intended and can cause a variety of otherwise cryptic
errors.</p><pre><code class="klipse-clojure nohighlight">(counted? "Hello")
;; ⇒ false
</code></pre><pre><code class="klipse-clojure nohighlight">;; will be fully realized when using (count (range 10))
(counted? (range 10))
;; ⇒ false
</code></pre><pre><code class="klipse-clojure nohighlight">;; Constant time return of (count)
(counted? [1 2 3 4 5])
;; ⇒ true
</code></pre><p><a id="empty?_desc"></a></p><h3 id="empty-1">empty?</h3><pre><code class="clojure">([coll])
</code></pre><p><code>empty</code> takes a collection.</p><p><code>empty?</code> returns true if the collection has no items, or false if it has 1 or more items.</p><pre><code class="klipse-clojure nohighlight">(empty? [])
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">(empty? '(1 2 3))
;; ⇒ false
</code></pre><p>Do not confuse <code>empty?</code> with <code>empty</code>. This can be a source of great confusion:</p><pre><code class="klipse-clojure nohighlight">(if (empty [1 2 3]) ;; empty returns an empty seq, which is true! use empty? here.
"It's empty"
"It's not empty")
;; ⇒ "It's empty"
</code></pre><p><a id="not-empty_desc"></a></p><h3 id="not-empty">not-empty</h3><pre><code class="clojure">([coll])
</code></pre><p><code>not-empty</code> takes a collection.</p><p><code>not-empty</code> returns nil if the collection has no items. If the collection contains items, the collection is returned.</p><pre><code class="klipse-clojure nohighlight">(not-empty '(:mice :elephants :children))
;; ⇒ (:mice :elephants :children)
</code></pre><pre><code class="klipse-clojure nohighlight">(not-empty '())
;; ⇒ nil
</code></pre><h2 id="items-in-a-collection-or-sequence">Items in a Collection or Sequence</h2><p><a id="first_desc"></a></p><h3 id="first">first</h3><pre><code class="clojure">([coll])
</code></pre><p><code>first</code> takes a collection.</p><p><code>first</code> returns the first item in the collection. <code>first</code> returns nil
if the argument is empty or is nil.</p><p>Note that for collections that do not guarantee order like some maps
and sets, the behaviour of <code>first</code> should not be relied on.</p><pre><code class="klipse-clojure nohighlight">(first (range 10))
;; ⇒ 0
</code></pre><pre><code class="klipse-clojure nohighlight">(first [:floor :piano :seagull])
;; ⇒ :floor
</code></pre><pre><code class="klipse-clojure nohighlight">(first [])
;; ⇒ nil
</code></pre><p><a id="rest_desc"></a></p><h3 id="rest">rest</h3><pre><code class="clojure">([coll])
</code></pre><p><code>rest</code> takes a collection.</p><p><code>rest</code> returns a seq of items starting with the second element in the
collection. <code>rest</code> returns an empty seq if the collection only
contains a single item.</p><p><code>rest</code> should also not be relied on when using maps and sets unless
you are sure ordering is guaranteed.</p><pre><code class="klipse-clojure nohighlight">(rest [13 1 16 -4])
;; ⇒ (1 16 -4)
</code></pre><pre><code class="klipse-clojure nohighlight">(rest '(:french-fry))
;; ⇒ '()
</code></pre><p>The behaviour of <code>rest</code> should be contrasted with <code>next</code>. <code>next</code>
returns nil if the collection only has a single item. This is
important when considering "truthiness" of values since an empty seq
is "true" but nil is not.</p><pre><code class="klipse-clojure nohighlight">(if (rest '("stuff"))
(print "Does this print?")) ;; yes, it prints.
</code></pre><pre><code class="clojure">;; NEVER FINISHES EXECUTION!
;; "done" is never reached because (rest x) is always a "true" value
(defn inf
[x]
(if (rest x)
(inf (rest x))
"done"))
</code></pre><p><a id="get_desc"></a></p><h3 id="get">get</h3><pre><code class="clojure">([map key])
([map key not-found])
</code></pre><p><code>get</code> takes an associative collection, a sequence of keys and an optional default value.</p><p><code>get</code> returns the value for the specified key in a map or record,
index of a vector or value in a set. If the key is not present, <code>get</code>
returns nil or a supplied default value.</p><pre><code class="klipse-clojure nohighlight">;; val of a key in a map
(get {:a 1 :b 2 :c 3} :b)
;; ⇒ 2
</code></pre><pre><code class="klipse-clojure nohighlight">;; index of a vector
(get [10 15 20 25] 2)
;; ⇒ 20
</code></pre><pre><code class="klipse-clojure nohighlight">;; in a set, returns the value itself if present
(get #{1 10 100 2 20 200} 1)
;; ⇒ 1
</code></pre><pre><code class="klipse-clojure nohighlight">;; returns nil if key is not present
(get {:a 1 :b 2} :c)
;; ⇒ nil
</code></pre><pre><code class="klipse-clojure nohighlight">;; vector does not have an _index_ of 4. nil is returned
(get [1 2 3 4] 4)
;; ⇒ nil
</code></pre><pre><code class="klipse-clojure nohighlight">(defrecord Hand [index middle ring pinky thumb])
(get (Hand. 3 4 3.5 2 2) :index)
;; ⇒ 3
</code></pre><p><code>get</code> also supports a default return value supplied as the last argument.</p><pre><code class="klipse-clojure nohighlight">;; index 4 does not exist. return default value
(get [1 2 3 4] 4 "Not Found")
;; ⇒ "Not Found"
</code></pre><pre><code class="klipse-clojure nohighlight">;; key :c does not exist, so return default value of 3
(get {:a 1 :b 2} :c 3)
;; ⇒ 3
</code></pre><p><a id="contains?_desc"></a></p><h3 id="contains">contains?</h3><pre><code class="clojure">([coll key])
</code></pre><p><code>contains?</code> takes a map and a key.</p><p><code>contains</code> returns true if the provided <em>key</em> is present in a
collection. <code>contains</code> is similar to <code>get</code> in that vectors treat the
key as an index. <code>contains</code> will always return false for lists.</p><pre><code class="klipse-clojure nohighlight">(contains? {:a 1 :b 2 :c 3} :c)
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">;; true if index 2 exists
(contains? ["John" "Mary" "Paul"] 2)
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">;; false if index 5 does not exist
(contains? ["John" "Mary" "Paul"] 5)
;; ⇒ false
</code></pre><pre><code class="klipse-clojure nohighlight">;; "Paul" does not exist as an index
(contains? ["John" "Mary" "Paul"] "Paul")
;; ⇒ false
</code></pre><pre><code class="klipse-clojure nohighlight">;; lists are not supported. contains? won't traverse a collection for a result.
(contains? '(1 2 3) 0)
;; ⇒ java.lang.IllegalArgumentException: contains? not supported on type: clojure.lang.PersistentList
</code></pre><p><a id="keys_desc"></a></p><h3 id="keys">keys</h3><pre><code class="clojure">([map])
</code></pre><p><code>keys</code> takes a map or record.</p><p><code>keys</code> returns a sequence of the keys in a map or record.</p><pre><code class="klipse-clojure nohighlight">(keys {1 "one" 2 "two" 3 "three"})
;; ⇒ (1 2 3)
</code></pre><pre><code class="klipse-clojure nohighlight">(defrecord Hand [index middle ring pinky thumb])
(keys (Hand. 2 4 3 1 2))
;; ⇒ (:index :middle :ring :pinky :thumb)
</code></pre><p><a id="vals_desc"></a></p><h3 id="vals">vals</h3><pre><code class="clojure">([map])
</code></pre><p><code>vals</code> takes a map or record.</p><p><code>vals</code> returns a sequence of vals in a map or record.</p><pre><code class="klipse-clojure nohighlight">(vals {:meows 20 :barks 2 :moos 5})
;; ⇒ (5 2 20)
</code></pre><pre><code class="klipse-clojure nohighlight">(defrecord Hand [index middle ring pinky thumb])
(vals (Hand. 1 2 3 4 5))
;; ⇒ (1 2 3 4 5)
</code></pre><p><a id="take_desc"></a></p><h3 id="take">take</h3><pre><code class="clojure">([n coll])
</code></pre><p><code>take</code> takes a number and a collection.</p><p><code>take</code> returns a lazy sequence starting with the first value of the
collection and n sequential items after that.</p><p>If the number of items in the collection is less than the provided
number, the entire collection is returned lazily.</p><pre><code class="clojure">TBD: example
</code></pre><p><a id="drop_desc"></a></p><h3 id="drop">drop</h3><pre><code class="clojure">([n coll])
</code></pre><p><code>drop</code> takes a number and a collection.</p><p><code>drop</code> returns a lazy sequence starting at the nth item of the collection.</p><pre><code class="clojure">TBD: example
</code></pre><p><a id="take-while_desc"></a></p><h3 id="take-while">take-while</h3><pre><code class="clojure">([pred coll])
</code></pre><p><code>take-while</code> takes a function that accepts a single-argument and a
collection.</p><p><code>take-while</code> returns a lazy sequence of sequential items until the
function returns nil/false value for that item.</p><pre><code class="clojure">TBD: example
</code></pre><p><a id="drop-while_desc"></a></p><h3 id="drop-while">drop-while</h3><pre><code class="clojure">([pred coll])
</code></pre><p>'drop-while` takes a function that accepts a single-argument and a
collection.</p><p><code>drop-while</code> returns a lazy sequence starting at the first item in the
collection that the function returns nil/false.</p><p><a id="filter_desc"></a></p><h3 id="filter">filter</h3><pre><code class="clojure">([pred coll])
</code></pre><p><code>filter</code> takes a function that accepts a single argument and a
collection.</p><p><code>filters</code> returns a lazy sequence of items that return <code>true</code> for the
provided predicate. Contrast to <code>remove</code>.</p><pre><code class="klipse-clojure nohighlight">(filter even? (range 10))
;; ⇒ (0 2 4 6 8)
</code></pre><pre><code class="klipse-clojure nohighlight">(filter #(if (&lt; (count %) 5) %) ["Paul" "Celery" "Computer" "Rudd" "Tayne"])
;; ⇒ ("Paul" "Rudd")
</code></pre><p>When using sets with <code>filter</code>, remember that if nil or false is in the
set and in the collection, then the predicate will return itself:
<code>nil</code>.</p><p>In this example, when nil and false are tested with the predicate, the
predicate returns nil. This is because if the item is present in the
set it is returned. This will cause that item to /not/ be included in
the returned lazy-sequence.</p><pre><code class="klipse-clojure nohighlight">(filter #{:nothing :something nil} [:nothing :something :things :someone nil false :pigeons])
;; ⇒ (:nothing :something)
</code></pre><p><a id="keep_desc"></a></p><h3 id="keep">keep</h3><p><code>(keep f coll)</code></p><p><code>keep</code> takes a function that accepts a single argument and a
collection.</p><p><code>keep</code> returns a lazy sequence of non-nil results of the function
applied to each item in the collection in sequence.</p><pre><code class="clojure">TBD: examples
</code></pre><p><a id="remove_desc"></a></p><h3 id="remove">remove</h3><pre><code class="clojure">([pred coll])
</code></pre><p><code>remove</code> takes a function that accepts a single argument and a
collection.</p><p><code>remove</code> returns a lazy sequence of items that return <code>false</code> or <code>nil</code>
for the provided predicate. Contrast to <code>filter</code>.</p><pre><code class="klipse-clojure nohighlight">(remove even? (range 10))
;; ⇒ (1 3 5 7 9)
</code></pre><pre><code class="klipse-clojure nohighlight">;; relative complement. probably useless?
(remove {:a 1 :b 2} [:h :k :z :b :s])
;; ⇒ (:h :k :z :s)
</code></pre><p>When using sets with <code>remove</code>, remember that if nil or false is in the
set and in the collection, then the predicate will return itself:
<code>nil</code>. This will cause that item to be included in the returned lazy
sequence.</p><p>In this example, when nil and false are tested with the predicate, the
predicate returns nil. This is because if the item is present in the
set it is returned.</p><pre><code class="klipse-clojure nohighlight">(remove #{:nothing :something nil} [:nothing :something :things :someone nil false :pigeons])
;; ⇒ (:things :someone nil false :pigeons)
</code></pre><p><a id="some_desc"></a></p><h3 id="some">some</h3><pre><code class="clojure">([pred coll])
</code></pre><p><code>some</code> takes a function that accepts a single argument and a collection.</p><p><code>some</code> will apply a predicate to each value in a collection until a
non-false/nil result is returned then immediately return that result.</p><p>Since collections are "true" values, this makes it possible to return
the first result itself rather than simply <code>true</code>.</p><pre><code class="klipse-clojure nohighlight">(some even? [1 2 3 4 5])
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">;; predicate returns the value rather than simply true
(some #(if (even? %) %) [1 2 3 4 5])
;; ⇒ 2
</code></pre><p>Since maps can be used as functions, you can use a map as a
predicate. This will return the value of the first key in the
collection that is also in the map.</p><pre><code class="klipse-clojure nohighlight">(some {:a 1 :b 5} [:h :k :d :b])
;; ⇒ 5
</code></pre><p>Sets can also be used as functions and will return the first item in
the collection that is present in the set.</p><pre><code class="klipse-clojure nohighlight">(some #{4} (range 20))
;; ⇒ 4
</code></pre><p><a id="every?_desc"></a></p><h3 id="every">every?</h3><pre><code class="clojure">([pred coll])
</code></pre><p><code>every</code> takes a function that accepts a single argument and a collection.</p><p><code>every</code> returns true if the predicate returns true for every item in
the collection, otherwise it returns false.</p><pre><code class="klipse-clojure nohighlight">(every? even? (range 0 10 2))
;; ⇒ true
</code></pre><pre><code class="klipse-clojure nohighlight">;; set can be used to see if collection only contains items in the set.
(every? #{2 3 4} [2 3 4 2 3 4])
;; ⇒ true
</code></pre><h2 id="processing-collections-and-sequences">Processing Collections and Sequences</h2><p><a id="partition_desc"></a></p><h3 id="partition">partition</h3><pre><code class="clojure">([n coll])
([n step coll])
([n step pad coll])
</code></pre><p><code>partition</code> takes a number, an optional step, an optional padding
collection and a collection. If the padding collection is provided, a
step must be provided.</p><p><code>partition</code> sequentially takes a provided number of items from the
collection in sequence and puts them into lists. This lazy sequence of
lists is returned.</p><p>If a step is provided, the lists in the returned lazy sequence start
at offsets in the provided collection of that number items in the
list.</p><p>If a padding collection is provided, the last item in the returned
lazy sequence will be padded with the padding collection to achieve
the desired partitioning size.</p><p>If there is no padding collection provided and there is not enough
items to fill the last list in the returned lazy sequence, those items
will be not used.</p><pre><code class="clojure">TBD: example
</code></pre><p><a id="partition-all_desc"></a></p><h3 id="partition-all">partition-all</h3><pre><code class="clojure">([n coll])
([n step coll])
</code></pre><p><code>partition-all</code> takes a number, an optional step and a collection.</p><p><code>partition-all</code> sequentially takes a provided number of items from the
collection in sequence and puts them into lists. This lazy sequence of
lists is returned.</p><p>If a step is provided, the lists in the returned lazy sequence start
at offsets in the provided collection of that number items in the
list.</p><p>If there are not enough items to fill the last list in the returned
lazy sequence, the remaining items will be used in the last list.</p><pre><code class="clojure">TBD: example
</code></pre><h3 id="filter-1">filter</h3><p>See: <a href="https://clojure-doc.org/articles/language/core_overview/filter_desc">filter</a></p><h3 id="remove-1">remove</h3><p>See: <a href="https://clojure-doc.org/articles/language/core_overview/remove_desc">remove</a></p><h3 id="for-2">for</h3><p>See: <a href="https://clojure-doc.org/articles/language/core_overview/for_desc">for</a></p><h3 id="map-1">map</h3><p>See: <a href="https://clojure-doc.org/articles/language/core_overview/map_desc">map</a></p><h3 id="remove-2">remove</h3><p>See: <a href="https://clojure-doc.org/articles/language/core_overview/remove_desc">remove</a></p><h3 id="empty-2">empty?</h3><p>See: <a href="https://clojure-doc.org/articles/language/core_overview/empty?_desc">empty</a></p><h3 id="not-empty-1">not-empty</h3><p>See: <a href="https://clojure-doc.org/articles/language/core_overview/not-empty_desc">not-empty</a></p><h2 id="function-composition-and-application">Function Composition and Application</h2><p><a id="juxt_desc"></a></p><h3 id="juxt">juxt</h3><pre><code class="clojure">([])
([f])
([f g])
([f g h])
([f1 f2 f3 &amp; fs])
</code></pre><p><code>juxt</code> takes a variable number of functions.</p><p><code>juxt</code> returns a function that will return a vector consisting of the
result of each of those functions to a provided argument.</p><pre><code class="clojure">TBD: examples
</code></pre><p>TBD: Simple image accompaniment.</p><p><a id="comp_desc"></a></p><h3 id="comp">comp</h3><pre><code class="clojure">([])
([f])
([f g])
([f g h])
([f1 f2 f3 &amp; fs])
</code></pre><p><code>comp</code> takes a variable number of functions.</p><p><code>comp</code> returns a function that will return the result of applying the
rightmost function to the provided argument, then the second rightmost
function to the result of that etc.</p><pre><code class="clojure">TBD: examples
</code></pre><p>TBD: Simple image accompaniment.</p><p><a id="fnil_desc"></a></p><h3 id="fnil">fnil</h3><pre><code class="clojure">([f x])
([f x y])
([f x y z])
</code></pre><p><code>fnil</code> takes a function and one to three arguments.</p><p><code>fnil</code> returns a function that replaces any nil arguments with the
provided values. <code>fnil</code> only supports supports patching 3 arguments,
but will pass any arguments beyond that un-patched.</p><pre><code class="klipse-clojure nohighlight">(defn say-info [name location hobby]
(println name "is from" location "and enjoys" hobby))
(def say-info-patched (fnil say-info "Someone" "an unknown location" "Clojure"))
(say-info-patched nil nil nil)
;; ⇒ Someone is from an unknown location and enjoys Clojure
</code></pre><pre><code class="klipse-clojure nohighlight">(say-info-patched "Robert" nil "giraffe migrations")
;; ⇒ Robert is from an unknown location and enjoys giraffe migrations
</code></pre><p><a id="apply_desc"></a></p><h3 id="apply">apply</h3><pre><code class="clojure">([f args] [f x args] [f x y args] [f x y z args] [f a b c d &amp; args])
</code></pre><p><code>apply</code> takes a variable number of arguments and a collection.</p><p><code>apply</code> effectively unrolls the supplied args and a collection into a
list of arguments to the supplied function.</p><pre><code class="klipse-clojure nohighlight">(str ["Hel" "lo"])
;; ⇒ "[\"Hel\" \"lo\"]" ;; not what we want, str is operating on the vector
</code></pre><pre><code class="klipse-clojure nohighlight">(apply str ["Hel" "lo"]) ;; same as (str "Hel" "lo")
;; ⇒ "Hello"
</code></pre><p><code>apply</code> prepends any supplied arguments to the form as well.</p><pre><code class="klipse-clojure nohighlight">(map + [[1 2 3] [1 2 3]]) ;; This attempts to add 2 vectors with +
;; ClassCastException java.lang.Class.cast (Class.java:2990)
</code></pre><pre><code class="klipse-clojure nohighlight">(apply map + [[1 2 3] [1 2 3]]) ;; same as (map + [1 2 3] [1 2 3])
;; ⇒ (2 4 6)
</code></pre><pre><code class="klipse-clojure nohighlight">(apply + 1 2 3 [4 5 6]) ;; same as (+ 1 2 3 4 5 6)
;; ⇒ 21
</code></pre><p>Note that apply can not be used with macros.</p><p><a id="-_desc"></a></p><h3 id="-">-&gt;</h3><pre><code class="clojure">([x])
([x form])
([x form &amp; more])
</code></pre><p><code>-&gt;</code> takes a value and optionally one or more expressions.</p><p><code>-&gt;</code> takes the first argument and inserts it as the second item in the
next form, or creates a list with the first argument as the second
item. The return value of that expression is inserted as the second
item in the next form, making a list if necessary. This continues
until all expressions are evaluated and the final value is returned.</p><pre><code class="clojure">TBD: example
</code></pre><p>TBD: Simple image accompaniment.</p><p><a id="-_desc"></a></p><h3 id="--1">-&gt;&gt;</h3><pre><code class="clojure">([x])
([x form])
([x form &amp; more])
</code></pre><p><code>-&gt;&gt;</code> takes a value and optionally one or more expressions.</p><p><code>-&gt;&gt;</code> takes the first argument and inserts it as the last item in the
next form, or creates a list with the first argument as the last
item. The return value of that expression is inserted as the last item
in the next form, making a list if necessary. This continues until
all expressions are evaluated and the final value is returned.</p><p>TBD: Simple image accompaniment.</p><h2 id="associative-collections">Associative Collections</h2><p><a id="get-in_desc"></a></p><h3 id="get-in">get-in</h3><pre><code class="clojure">([m ks] [m ks not-found])
</code></pre><p><code>get-in</code> takes an associative collection, a sequence of keys and an optional default value.</p><p><code>get-in</code> takes the first value in the sequence of keys and retrieves
the value, then applies each subsequent key to to the most recently
returned value and returns the final result. If any key is not present
when evaluated then either nil, or a provided default value is
returned.</p><pre><code class="klipse-clojure nohighlight">(get-in {:profile {:personal {:age 28}}} [:profile :personal :age])
;= 28
</code></pre><p>TBD: Simple image accompaniment.</p><p><a id="update-in_desc"></a></p><h3 id="update-in">update-in</h3><pre><code class="clojure">([m [k &amp; ks] f &amp; args])
</code></pre><p><code>update-in</code> takes an associative collection, a sequence of keys, a
function and optional arguments to supply to that function.</p><p><code>update-in</code> takes the first value in the sequence of keys and
retrieves the value, then applies each subsequent key to to the most
recently returned value. The function and optional arguments are
applied to the value and a new nested collection is returned with the
key having the result of that function.</p><p><code>update-in</code> will create new hash-maps if a key in the sequence of keys
does not exist. The returned collection will have a nested structure
correlating to the provided sequence along with the result of the
function and optional arguments as the value of the final key.</p><pre><code class="klipse-clojure nohighlight">(update-in {:profile {:personal {:age 28}}} [:profile :personal :age] inc)
;= {:profile {:personal {:age 29}}}
</code></pre><p>TBD: Simple image accompaniment.</p><p><a id="assoc-in_desc"></a></p><h3 id="assoc-in">assoc-in</h3><pre><code class="clojure">([m [k &amp; ks] v])
</code></pre><p><code>assoc-in</code> takes an associative collection, a sequence of keys and a value.</p><p><code>assoc-in</code> takes the first value in the sequence of keys and retrieves
the value, then applies each subsequent key to to the most recently
returned value. The final key is assigned the provided value and a new
nested collection is returned.</p><p><code>update-in</code> will create new hash-maps if a key in the sequence of keys
does not exist. The returned collection will have a nested structure
correlating to the provided sequence along with the provided value as
the value of the final key.</p><pre><code class="klipse-clojure nohighlight">(assoc-in {:profile {:personal {:age 28}}} [:profile :personal :location] "Vancouver, BC")
;= {:profile {:personal {:location "Vancouver, BC", :age 28}}}
</code></pre><p>TBD: Simple image accompaniment.</p><p><a id="select-keys_desc"></a></p><h3 id="select-keys">select-keys</h3><pre><code class="clojure">([map keyseq])
</code></pre><p><code>select-keys</code> takes an associative collection and a sequence of keys.</p><p><code>select-keys</code> returns a map containing only the entries that have a
key which is also present in the sequence of keys.</p><pre><code class="klipse-clojure nohighlight">(select-keys {:a 1 :b 2 :c 3} [:a :b])
;= {:b 2, :a 1}
</code></pre><h3 id="keys-1">keys</h3><p>See: <a href="index.html#keys_desc">keys</a></p><h3 id="vals-1">vals</h3><p>See: <a href="index.html#vals_desc">vals</a></p><h3 id="get-1">get</h3><p>See: <a href="index.html#get_desc">get</a></p><h3 id="assoc-1">assoc</h3><p>See: <a href="index.html#assoc_desc">assoc</a></p><h3 id="dissoc-1">dissoc</h3><p>See: <a href="index.html#dissoc_desc">dissoc</a></p><h2 id="namespace-functions">Namespace Functions</h2><p><a id="ns_desc"></a></p><h3 id="ns-require-use-import-refer">ns, require, use, import, refer</h3><p>Please see the <a href="../namespaces/index.html">Namespace guide</a></p><h2 id="reference-types">Reference Types</h2><p><a id="ref_desc"></a></p><h3 id="ref-atom-var-agent">ref, atom, var, agent</h3><p>Please see the <a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism Guide</a></p><p><a id="deref_desc"></a></p><h3 id="deref-swap-reset-dosync-alter-commute-binding">deref, swap!, reset!, dosync, alter, commute, binding</h3><p>Please see the <a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism Guide</a></p><h2 id="contributors">Contributors</h2><p>Robert Randolph <a href="mailto:audiolabs@gmail.com">audiolabs@gmail.com</a> (original author)
Michael Klishin <a href="mailto:michael@defprotocol.org">michael@defprotocol.org</a>
Nguyễn Hà Dương <a href="mailto:cmpitg@gmail.com">cmpitg@gmail.com</a></p>
<div id="prev-next">
<a href="../../tutorials/growing_a_dsl_with_clojure/index.html">&laquo; Growing a DSL with Clojure</a>
||
<a href="../namespaces/index.html">Clojure Namespaces and Vars &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../functions/index.html">Functions in Clojure</a></li>
<li><a href="../laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
<link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">
<script>
window.klipse_settings = {
"selector" : ".klipse-clojure"
};
</script>
<script src="https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"></script>
</body>
</html>

View file

@ -0,0 +1,398 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Functions in Clojure</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/functions/" />
<meta property="og:title" content="Functions in Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/functions/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Functions in Clojure</h2>
</div>
<p>This guide covers:</p><ul><li>How to define functions</li><li>How to invoke functions</li><li>Multi-arity functions</li><li>Variadic functions</li><li>Higher order functions</li><li>Other topics related to functions</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5.</p><h2 id="overview">Overview</h2><p>Clojure is a functional programming language. Naturally, functions are very important part of Clojure.</p><h2 id="how-to-define-functions">How To Define Functions</h2><p>Functions are typically defined using the <a href="http://clojuredocs.org/clojure_core/clojure.core/defn">defn</a> macro:</p><pre><code class="clojure">(defn round
[d precision]
(let [factor (Math/pow 10 precision)]
(/ (Math/floor (* d factor)) factor)))
</code></pre><p>Functions can have doc strings (documentation strings) and it is a good idea to document functions that
are part of the public API:</p><pre><code class="clojure">(defn round
"Round down a double to the given precision (number of significant digits)"
[d precision]
(let [factor (Math/pow 10 precision)]
(/ (Math/floor (* d factor)) factor)))
</code></pre><p>In Clojure, function arguments may have optional type hints:</p><pre><code class="clojure">(defn round
[^double d ^long precision]
(let [factor (Math/pow 10 precision)]
(/ (Math/floor (* d factor)) factor)))
</code></pre><p>Type hints sometimes allow the compiler to avoid reflective method calls and/or produce significantly more efficient bytecode.
However, as a rule of thumb, it is usually not necessary to use type hints. Start writing your code without them. The compiler
is also free to ignore provided hints.</p><p>Functions can also define <em>preconditions</em> and <em>postconditions</em> that put restrictions on argument values and
the value function returns:</p><pre><code class="clojure">(defn round
"Round down a double to the given precision (number of significant digits)"
[^double d ^long precision]
{:pre [(not-nil? d) (not-nil? precision)]}
(let [factor (Math/pow 10 precision)]
(/ (Math/floor (* d factor)) factor)))
</code></pre><p>In the example above, we use preconditions to check that both arguments are not nil. The <code>not-nil?</code> macro (or function) is not
demonstrated in this example and assumed to be implemented elsewhere.</p><h2 id="anonymous-functions">Anonymous Functions</h2><p>Anonymous functions are defined using the <code>fn</code> special form:</p><pre><code class="clojure">(fn [x]
(* 2 x))
</code></pre><p>Anonymous functions can be assigned to locals, passed between functions (higher order functions are covered later in this document)
and returned from functions:</p><pre><code class="klipse-clojure nohighlight">(let [f (fn [x]
(* 2 x))]
(map f (range 0 10)))
</code></pre><p>There is also a reader macro for anonymous functions:</p><pre><code class="klipse-clojure nohighlight">(let [f #(* 2 %)]
(map f (range 0 10)))
</code></pre><p>The <code>%</code> in the example above means "the first argument". To refer to more than one argument, use <code>%1</code>, <code>%2</code> and so on:</p><pre><code class="klipse-clojure nohighlight">;; an anonymous function that takes 3 arguments and adds them together
(let [f #(+ %1 %2 %3)]
(f 1 2 3))
</code></pre><p>Please <strong>use this reader macro sparingly</strong>; excessive use may lead to unreadable code.</p><h2 id="how-to-invoke-functions">How To Invoke Functions</h2><p>Functions are invoked by placing a function to the leading position (<em>the calling position</em>) of a list:</p><pre style="visibility:hidden; height:0;"><code class="klipse-clojure nohighlight">
(import '(goog.string format))
</code></pre><pre><code class="klipse-clojure nohighlight">(format "Hello, %s" "world")
</code></pre><p>This works also if you have a function stored in a local, a var or passed as an argument:</p><pre><code class="klipse-clojure nohighlight">(let [f format]
(f "Hello, %s" "world"))
</code></pre><p>Alternatively, you can call a function using <a href="http://clojuredocs.org/clojure_core/clojure.core/apply">clojure.core/apply</a></p><pre><code class="klipse-clojure nohighlight">(apply format "Hello, %s" ["world"])
</code></pre><pre><code class="klipse-clojure nohighlight">(apply format "Hello, %s %s" ["Clojure" "world"])
</code></pre><p><code>clojure.core/apply</code> is usually only necessary when calling variadic functions or having the list of arguments passed in
as a collection.</p><h2 id="multi-arity-functions">Multi-arity Functions</h2><p>Functions in Clojure can have multiple <em>arities</em>, or sets of arguments:</p><pre><code class="clojure">(defn tax-amount
([amount]
(tax-amount amount 35))
([amount rate]
(Math/round (double (* amount (/ rate 100))))))
</code></pre><p>In the example above, the version of the function that takes only one argument (so called <em>one-arity</em> or <em>1-arity</em> function)
calls another version (<em>2-arity</em>) with a default parameter. This is a common use case for multiple arities: to have default
argument values. Clojure is a hosted language and JVM (and JavaScript VMs, for that matter) does not support default argument
values, however, it does support <em>method overloading</em> and Clojure takes advantage of this.</p><p>Arities in Clojure can only differ by the number of arguments, not types. This is because Clojure is strongly dynamically typed language and type information about
parameters may or may not be available to the compiler.</p><p>A larger example:</p><pre><code class="clojure">(defn range
([]
(range 0 Double/POSITIVE_INFINITY 1))
([end]
(range 0 end 1))
([start end]
(range start end 1))
([start end step]
(comment Omitted for clarity)))
</code></pre><h2 id="destructuring-of-function-arguments">Destructuring of Function Arguments</h2><p>Sometimes function arguments are data structures: vectors, sequences, maps. To access parts of such
data structure, you may do something like this:</p><pre><code class="clojure">(defn currency-of
[m]
(let [currency (get m :currency)]
currency))
</code></pre><p>For vector arguments:</p><pre><code class="clojure">(defn currency-of
[pair]
(let [amount (first pair)
currency (second pair)]
currency))
</code></pre><p>However, this is boilerplate code that has little to do with what the function really does. Clojure
lets developer <strong>destructure</strong> parts of arguments, for both maps and sequences.</p><h3 id="positional-destructuring">Positional Destructuring</h3><p>Destructuring over vectors (<strong>positional destructuring</strong>) works like this: you replace the argument
with a vector that has "placeholders" (symbols) in positions you want to bind. For example, if the
argument is known to be a pair and you need second argument, it would look like this:</p><pre><code class="clojure">(defn currency-of
[[amount currency]]
currency)
</code></pre><p>In the example above the first element in the pair is bound to <code>amount</code> and the second one is bound to
<code>currency</code>. So far so good. However, notice that we do not use the <code>amount</code> local. In that case, we can
ignore it by replacing it with an underscore:</p><pre><code class="clojure">(defn currency-of
[[_ currency]]
currency)
</code></pre><p>Destructuring can nest (destructure deeper than one level):</p><pre><code class="clojure">(defn first-first
[[[i _] _]]
i)
</code></pre><p>While this article does not cover <code>let</code> and locals, it is worth demonstrating that positional destructuring works
exactly the same way for let bindings:</p><pre><code class="klipse-clojure nohighlight">(let [pair [10 :gbp]
[_ currency] pair]
currency)
</code></pre><h3 id="map-destructuring">Map Destructuring</h3><p>Destructuring over maps and records (<strong>map destructuring</strong>) works slightly differently:</p><pre><code class="clojure">(defn currency-of
[{currency :currency}]
currency)
</code></pre><p>In this case example, we want to bind the value for key <code>:currency</code> to <code>currency</code>. Keys don't have to be
keywords:</p><pre><code class="clojure">(defn currency-of
[{currency "currency"}]
currency)
</code></pre><pre><code class="clojure">(defn currency-of
[{currency 'currency}]
currency)
</code></pre><p>When destructuring multiple keys at once, it is more convenient to use a slightly different syntax:</p><pre><code class="clojure">(defn currency-of
[{:keys [currency amount]}]
currency)
</code></pre><p>The example above assumes that map keys will be keywords and we are interested in two values: <code>currency</code>
and <code>amount</code>. The same can be done for strings:</p><pre><code class="clojure">(defn currency-of
[{:strs [currency amount]}]
currency)
</code></pre><p>and symbols:</p><pre><code class="clojure">(defn currency-of
[{:syms [currency amount]}]
currency)
</code></pre><p>In practice, keywords are very commonly used for map keys so destructuring with <code>{:keys [...]}</code> is very common
as well.</p><p>Map destructuring also lets us specify default values for keys that may be missing:</p><pre><code class="clojure">(defn currency-of
[{:keys [currency amount] :or {currency :gbp}}]
currency)
</code></pre><p>This is very commonly used for implementing functions that take "extra options" (faking named arguments support).</p><p>Just like with positional destructuring, map destructuring works exactly the same way for let bindings:</p><pre><code class="klipse-clojure nohighlight">(let [money {:currency :gbp :amount 10}
{currency :currency} money]
currency)
</code></pre><h2 id="variadic-functions">Variadic Functions</h2><p>Variadic functions are functions that take varying number of arguments (some arguments are optional). Two examples
of such function in <code>clojure.core</code> are <code>clojure.core/str</code> and <code>clojure.core/format</code>:</p><pre><code class="klipse-clojure nohighlight">(str "a" "b")
; ⇒ "ab"
</code></pre><pre><code class="klipse-clojure nohighlight">(str "a" "b" "c")
; ⇒ "abc"
</code></pre><pre><code class="klipse-clojure nohighlight">(format "Hello, %s" "world")
; ⇒ "Hello, world"
</code></pre><pre><code class="klipse-clojure nohighlight">(format "Hello, %s %s" "Clojure" "world")
; ⇒ "Hello, Clojure world"
</code></pre><p>To define a variadic function, prefix optional arguments with an ampersand (<code>&amp;</code>):</p><pre><code class="clojure">(defn log
[message &amp; args]
(comment ...))
</code></pre><p>In the example above, one argument is required and the rest is optional. Variadic functions
are invoked as usual:</p><pre><code class="klipse-clojure nohighlight">(defn log
[message &amp; args]
(println "args: " args))
(log "message from " "192.0.0.76")
</code></pre><pre><code class="klipse-clojure nohighlight">(log "message from " "192.0.0.76" "service:xyz")
</code></pre><p>As you can see, optional arguments (<code>args</code>) are packed into a list.</p><h3 id="extra-arguments-aka-named-parameters">Extra Arguments (aka Named Parameters)</h3><p>Named parameters are achieved through the use of destructuring a variadic function.</p><p>Approaching named parameters from the standpoint of destructuring a variadic function allows for more clearly readable function invocations. This is an example of named parameters:</p><pre><code class="klipse-clojure nohighlight">(defn job-info
[&amp; {:keys [name job income] :or {job "unemployed" income "$0.00"}}]
(if name
[name job income]
(println "No name specified")))
</code></pre><p>Using the function looks like this:</p><pre><code class="klipse-clojure nohighlight">(job-info :name "Robert" :job "Engineer")
;; ["Robert" "Engineer" "$0.00"]
</code></pre><pre><code class="klipse-clojure nohighlight">(job-info :job "Engineer")
;; No name specified
</code></pre><p>Without the use of a variadic argument list, you would have to call the function with a single map argument such as <code>{:name "Robert" :job "Engineer}</code>.</p><p>Keyword default values are assigned by use of the <code>:or</code> keyword followed by a map of keywords to their default value.
Keywords not present and not given a default will be nil.</p><h2 id="higher-order-functions">Higher Order Functions</h2><p>Higher-order functions (<em>HOFs</em>) are functions that take other functions as arguments. HOFs
are an important functional programming technique and are quite commonly used in Clojure. One example
of an HOF is a function that takes a function and a collection and returns a collection of elements
that satisfy a condition (a predicate). In Clojure, this function is called <code>clojure.core/filter</code>:</p><pre><code class="klipse-clojure nohighlight">(filter even? (range 0 10)) ; ⇒ (0 2 4 6 8)
</code></pre><p>In the example above, <code>clojure.core/filter</code> takes <code>clojure.core/even?</code> as an argument.</p><p><code>clojure.core</code> has dozens of other higher-order functions. The most commonly used ones are covered in <a href="../core_overview/index.html">clojure.core Overview</a>.</p><h2 id="private-functions">Private Functions</h2><p>Functions in Clojure can be private to their namespace.</p><p>They are covered in more detail in the <a href="../namespaces/index.html">Namespaces</a> guide.</p><h2 id="keywords-as-functions">Keywords as Functions</h2><p>In Clojure, keywords can be used as functions. They take a map or record and look themselves up in it:</p><pre><code class="klipse-clojure nohighlight">(:age {:age 27 :name "Michael"})
; ⇒ 27
</code></pre><p>This is commonly used with higher order functions:</p><pre><code class="klipse-clojure nohighlight">(map :age [{:age 45 :name "Joe"}
{:age 42 :name "Jill"}
{:age 17 :name "Matt"}])
;; ⇒ (45 42 17)
</code></pre><p>and the <code>-&gt;</code> macro:</p><pre><code class="klipse-clojure nohighlight">(-&gt; [{:age 45 :name "Joe"} {:age 42 :name "Jill"}]
first
:name)
;; ⇒ "Joe"
</code></pre><h2 id="maps-as-functions">Maps as Functions</h2><p>Clojure maps are also functions that take keys and look up values for them:</p><pre><code class="klipse-clojure nohighlight">({:age 42 :name "Joe"} :name)
; ⇒ "Joe"
</code></pre><pre><code class="klipse-clojure nohighlight">({:age 42 :name "Joe"} :age)
; ⇒ 42
</code></pre><pre><code class="klipse-clojure nohighlight">({:age 42 :name "Joe"} :unknown)
; ⇒ nil
</code></pre><p>Note that this is <strong>not true</strong> for Clojure records, which are almost identical to maps in other
cases.</p><h2 id="sets-as-functions">Sets as Functions</h2><pre><code class="klipse-clojure nohighlight">(#{1 2 3} 1)
; ⇒ 1
</code></pre><pre><code class="klipse-clojure nohighlight">(#{1 2 3} 10)
; ⇒ nil
</code></pre><pre><code class="klipse-clojure nohighlight">(#{:us :au :ru :uk} :uk)
; ⇒ :uk
</code></pre><pre><code class="klipse-clojure nohighlight">(#{:us :au :ru :uk} :cn)
; ⇒ nil
</code></pre><p>This is often used to check if a value is in a set:</p><pre><code class="clojure">(when (countries :in)
(comment ...))
(if (countries :in)
(comment Implement positive case)
(comment Implement negative case))
</code></pre><p>because everything but <code>false</code> and <code>nil</code> evaluates to <code>true</code> in Clojure.</p><h2 id="clojure-functions-as-comparators">Clojure Functions As Comparators</h2><p>Clojure functions implement the <a href="http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html">java.util.Comparator</a>
interface and can be used as comparators.</p><h2 id="wrapping-up">Wrapping Up</h2><p>Functions are at the heart of Clojure. They are defined using the <code>defn</code> macro, can have multiple arities,
be variadic and support parameter destructuring. Function arguments and return value can optionally be
type hinted.</p><p>Functions are first class values and can be passed to other functions (called Higher Order Functions or HOFs).
This is fundamental to functional programming techniques.</p><p>Several core data types behave like functions. When used reasonably, this can lead to more concise, readable
code.</p><h2 id="contributors">Contributors</h2><p>Michael Klishin <a href="mailto:michael@defprotocol.org">michael@defprotocol.org</a>, 2012 (original author)</p>
<div id="prev-next">
<a href="../collections_and_sequences/index.html">&laquo; Collections and Sequences in Clojure</a>
||
<a href="../laziness/index.html">Laziness in Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="index.html">Functions in Clojure</a></li>
<li><a href="../laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
<link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">
<script>
window.klipse_settings = {
"selector" : ".klipse-clojure"
};
</script>
<script src="https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"></script>
</body>
</html>

View file

@ -0,0 +1,344 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Clojure Terminology Guide</title>
<meta name="description" content="A glossary of terminology specific to Clojure. Terms
are listed in alphabetical order.Terms">
<meta property="og:description" content="A glossary of terminology specific to Clojure. Terms
are listed in alphabetical order.Terms">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/glossary/" />
<meta property="og:title" content="Clojure Terminology Guide" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/glossary/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Clojure Terminology Guide</h2>
</div>
<p>A glossary of terminology specific to Clojure. Terms
are listed in alphabetical order.</p><h2 id="terms">Terms</h2><h3 id="arity">arity</h3><p>The number of arguments a function takes is its arity. If it's
written to take a variable number of args, it's referred to as
<a href="index.html#variadic">variadic</a>.</p><p>Functions can have multiple arity (for example, a function might have
2 different bodies: one for when 2 args are passed, and another when 3
args are passed).</p><h3 id="binding-form">binding-form</h3><p>Could mean one of two things:</p><ol><li><p>the expression you're binding to in a
<a href="index.html#let_binding">let-binding</a>. It might be a simple name, or it
might be a data structure used for
<a href="index.html#destructuring">destructuring</a>.</p></li><li><p>Clojure provides the <code>binding</code> macro, used for setting the
thread-local value of a dynamic var. The whole expression (form)
is sometimes referred to as the "binding <a href="index.html#form">form</a>".</p></li></ol><h3 id="classpath">classpath</h3><p>The search path used by the JVM to locate classes which are not
part of the Java standard class library. May include jar files.</p><h3 id="comparator">comparator</h3><p>A function that takes two args and compares them. Returns -1, 0, or 1
depending whether the first arg is less than, equal to or greater than
the second. The stock comparator that Clojure.core comes with is
<code>compare</code>.</p><h3 id="coordinates">coordinates</h3><p>The "group-id/artifact-id version-string" identifier used in your
project.clj to indicate a particular dependency.</p><p>See also <a href="index.html#libspec">libspec</a>.</p><h3 id="destructuring">destructuring</h3><p>The handy trick used in a <a href="index.html#let_binding">let-binding</a> to "unpack" the
values from a data structure into the locals you're going to use. See
also <a href="index.html#binding-form">binding-form</a> and <a href="https://clojure-doc.org/articles/language/glossary/functions.html#destructuring_of_function_arguments">the destructuring section in
the functions
guide</a>.</p><h3 id="dereference">dereference</h3><p>To get the value of a reference type. You can use the <code>deref</code> function
for this, or else some syntactic sugar: <code>@some-ref-type</code>.</p><h3 id="entry">entry</h3><p>A key/value pair in a map. Try <code>(type (first {:a 1 :b 2}))</code> and see
that it returns <code>clojure.lang.MapEntry</code>.</p><h3 id="evaluator">evaluator</h3><p><em>todo</em></p><h3 id="form">form</h3><p>A valid s-expression. For example: <code>(+ 1 1)</code> and <code>(defn foo [x] (* x x))</code>.</p><h3 id="head-retention">head retention</h3><p><a href="index.html#lazy">Lazy</a> sequences are still <a href="index.html#persistence">persistent</a>. If you
make <em>another</em> data structure using one, the original lazy sequence
will be kept around and not garbage-collected. If the lazy sequence in
infinite, and grows very large, it can cause performance problems or
even an out-of-memory error. Accidentally keeping around a lazy
sequence like this is referred to as "head retention".</p><h3 id="homoiconicity">homoiconicity</h3><p>Where the code and the data is represented by the same structure.
This allows the code to be treated as data, and the data to be treated
as code. This feature of Clojure, and other Lisps, allows for
macros in the language, since they can operate on code as a data
structure, and to return a transformation of that structure to
be the representation of new code.</p><h3 id="idempotent">idempotent</h3><p>An operation that when given the same inputs will produce the same
result when called one or more times. An idempotent function may
produce a side effect, such a updating a ref or an atom, but will
only produce the side effect once. An idempotent function is
different than a pure function, in that a pure function will
produce no side effects.</p><h3 id="identity">identity</h3><p>A logical entity in your program that may change over time --- it may
take on different states at different times, but it still means the
same logical entity. Clojure uses <a href="index.html#reference_types">reference types</a>
to represent identities. This is not to be confused with the <code>identity</code> function that just returns the argument given to it.</p><h3 id="implicit-do">implicit do</h3><p>The bodies of some expressions act like <code>do</code> in that you can include
multiple expressions in them, and the expressions will be evaluated in
the order they appear, with the resulting value of the body being the
last expression evaluated. Forms that do this include: <code>when</code>,
<code>when-let</code>, <code>fn</code>, <code>defn</code>, <code>let</code>, <code>loop</code>, and <code>try</code>.</p><h3 id="intern">intern</h3><p>A method of storing values or immutable data structures as a single
copy of the item, allowing for more space-efficiency, and possibly
time-efficiency, with the trade off of requiring more time being
required when interning the item. When the string "clojure" is interned,
all instances of the string "clojure" will reference the exact same
instance, instead of having multiple string objects with the same value
of "clojure".</p><h3 id="keyword">keyword</h3><p>A Clojure scalar data type whose literal syntax looks <code>:like</code> <code>:this</code>.
They are like numbers and strings in that they evaluate to themselves,
and are most often seen being used as keys in <a href="index.html#map">hash-maps</a>.</p><p>See also <a href="index.html#namespaced_keyword">namespaced keyword</a></p><p>The term is also used when talking about functions that take "keyword
arguments", for example, something like: <code>(my-func :speed 42 :mass 2)</code>
(as opposed to <code>(my-func {:speed 42 :mass 2})</code>).</p><h3 id="lazy">lazy</h3><p>Clojure can (and often does) create sequences for you that aren't
fully computed. Upon casual inspection they <em>look</em> just like a regular
list, but particular values in them are only computed the moment you
ask for them --- not sooner.</p><p>This has the added benefit that you can easily create infinite
sequences that don't consume infinite memory.</p><p>Many of the built-in Clojure functions return lazy sequences.</p><p>See also <a href="index.html#realize">realize</a>.</p><h3 id="let-binding">let-binding</h3><p>AKA, "binding vector", or just "bindings": in a <code>let</code> (and expressions
that work like let, for example, <code>defn</code>, <code>loop</code>, <code>loop</code>, &amp; <code>fn</code>), the
vector that comes first where you specify lexical bindings.</p><p>See also <a href="index.html#binding_form">binding form</a></p><h3 id="libspec">libspec</h3><p><em>todo</em></p><h3 id="macro">macro</h3><p>A special type of function which is transforms a S-Expression read in
and applies a transformation to the S-Expression resulting in a new
form. This process is called macro-expansion, and is done as part
of the Clojure reader.</p><h3 id="map">map</h3><p>Either refers to the built in <code>map</code> function, or else means "a
hash-map object".</p><h3 id="memoization">memoization</h3><p>The ability to cache a result of a function call by given arguments,
and return the result without having to do the calculation again.
Memoization is a time-space trade off in that more memory is used
to store the results of a function call to be able to return the
value instead of having to keep spending time doing the calculation
involved in the function.</p><h3 id="metadata">metadata</h3><p>An extra map that you can attach to a collection value (or a symbol),
which contains data about the data you're attaching it to. Use <code>meta</code>
to see the metadata of a given value.</p><h3 id="namespaced-keyword">namespaced keyword</h3><p>When you put two colons in front of a keyword's name --- for example
::foo --- it is a so-called "namespaced keyword", and is expanded by
the reader to become :current-namespace/foo.</p><h3 id="nullipotent">nullipotent</h3><p>An operation with no side effects. The result of calling the function
one or more times is the same as if it was never called. Queries are
typically good examples of functions that are nullipotent, as they
do not modify the state of the object or structure they are queried
against.</p><h3 id="persistence">persistence</h3><p>See the <a href="https://clojure-doc.org/articles/language/tutorials/introduction.html#values_immutability_and_persistence">relevant section of the
introduction</a>.</p><h3 id="predicate">predicate</h3><p>A function taking one or more args and returning a boolean (<code>true</code> or
<code>false</code>). Its name typically ends with a question mark. Some examples:
<code>nil?</code>, <code>zero?</code>, <code>string?</code>.</p><h3 id="pure-function">pure function</h3><p>A function that given the same inputs will always produce the same
result. A pure function also does not have any observable side effects
and cannot depend on any outside state, other than that which was given
as arguments to the function. A pure function's result also cannot change
during the execution of the program or between executions of the program,
as the dependency on outside state can lead to changes in the result of
the function. Pure functions are also
<a href="index.html#referential-transparency">referentially transparent.</a></p><h3 id="reader">reader</h3><p><em>todo</em></p><h3 id="reader-macro">reader macro</h3><p>Syntax that the Clojure reader recognizes as special syntactic sugar,
for example, <code>#""</code>, <code>#{}</code>, quoting, etc.</p><h3 id="realize">realize</h3><p>When the next value in a <a href="index.html#lazy">lazy</a> sequence is accessed for the
first time, and is computed so as to made available, it is said to
have been "realized". This term is also used to refer to the status of <a href="https://clojure-doc.org/articles/language/glossary/concurrency_and_parallelism.html#promises">promises</a>, <a href="https://clojure-doc.org/articles/language/glossary/concurrency_and_parallelism.html#futures">futures</a>, and <a href="https://clojure-doc.org/articles/language/glossary/concurrency_and_parallelism.html#delays">delays</a>. That is, if a promise (for example) is realized then that means its value has been delivered and is accessible via <a href="index.html#dereference">dereferencing</a>.</p><h3 id="reference-types">reference types</h3><p>Vars, atoms, refs, and agents are all reference types. They are
mutable in the sense that you can change to what value they refer, and
Clojure provides thread-safe mechanisms for doing so.</p><h3 id="referential-transparency">referential transparency</h3><p>An expression that will always return the same result for the values
given, and can be substituted for the resulting value, without
effecting the program. The advantage of referential transparent
expressions is that they can be memoized, and be the subject of
various compilier optimizations.</p><h3 id="reify">reify</h3><p><em>todo</em></p><h3 id="repl">REPL</h3><p>Short for: "Read, Eval, Print, Loop". The REPL reads in text through
the <a href="index.html#reader">reader</a> transforming it into a Clojure data structure,
<a href="index.html#evaluator">evaluates</a> the data structure as code, prints the result
of the evaluation, and loops back waiting to read the next input string.</p><h3 id="rest-args">rest args</h3><p>The extra args passed to a <a href="index.html#variadic">variadic</a> function, for example
if <code>my-func</code> were defined like <code>(defn my-func [a b &amp; more] ...)</code>, then
called like <code>(my-func 1 2 3 4 5)</code>, then 3, 4, &amp; 5 are the "rest args".</p><h3 id="s-expression">s-expression</h3><p>Short for Symbolic Expression. A S-Expression is a data structure able
to represent both simple datastructes such as literals, or complex data
structures such as nested expressions. Due to their versatile nature,
S-Expressions are able to represent both data in Clojure, as well as
the Clojure code itself, allowing Clojure to be a
<a href="index.html#homoiconicity">homoiconic</a> language.</p><h3 id="state">state</h3><p>The <a href="index.html#value">value</a> that a given <a href="index.html#identity">identity</a> may have at a
given time. When you change the state of an identity, you're changing
to which value it refers. Clojure uses values to represent states.</p><h3 id="stm-software-transactional-memory">STM (Software Transactional Memory)</h3><p>Software Transactional Memory (STM) is a concurrency control method to
coordinate and control access to shared storage as an alternative to
lock-based synchronization. Clojure's STM uses multiversion concurrency
control (MVCC) as an alternative to lock-based transactions, as well as
ensuring changes are made atomically, consistently, and in
isolation. It does this by taking a snapshot of the ref, making the
changes in isolation to the snapshot, and apply the result. If the STM
detects that another transaction has made an update to the ref, the
current transaction will be forced to retry.</p><h3 id="symbol">symbol</h3><p>An identifier that refers to vars or local values.</p><h3 id="tagged-literals">tagged literals</h3><p>(Formerly called "reader literals".)</p><p>Some literals begin with a hash mark "#" (so-called "dispatch
macros"); for example, <code>#{}</code> for sets and <code>#""</code> for regex
literals. Starting with Clojure 1.4, you can create your own
#-prefixed literal which causes the reader to parse the form
following it using a function or macro of your own
choosing/devising. It's in this way that you can <em>tag</em> a literal to be
handled specially by the reader.</p><p>For more info, see <a href="http://clojure.org/reader">the "Tagged Literals" section of the reader
doc</a>.</p><h3 id="threading-macros">threading macros</h3><p>The thread-first (<code>-&gt;</code>) and thread-last (<code>-&gt;&gt;</code>) macros. "Threading"
refers to how they pass values to each subsequent argument in the
macro, not concurrency.</p><h3 id="thrush">thrush</h3><p>A combinator. Not the same thing as the <a href="index.html#threading-macros">thread-first
macro</a>. More info at
<a href="http://blog.fogus.me/2010/09/28/thrush-in-clojure-redux/">http://blog.fogus.me/2010/09/28/thrush-in-clojure-redux/</a> if you're
curious.</p><h3 id="transaction">transaction</h3><p><em>todo</em></p><h3 id="type-erasure">type erasure</h3><p>Java-related: Java generics allow you to specify a type for a
collection. This way you don't have to cast every object you pull out
of an ArrayList like in the old days. This is a courtesy of the java
compiler. The java runtime doesn't know about generics --- the
compiler does all the checking for you, then the type information is
discarded at runtime. In Clojure, this discarding is referred to as
type erasure.</p><h3 id="value">value</h3><p>An immutable object, such as the number 1, the character <code>\a</code>, the
string "hello", or the vector <code>[1 2 3]</code>. In Clojure, all scalars and
built-in core data structures are values.</p><h3 id="variadic">variadic</h3><p>A function that can take a variable number of arguments.
See also <a href="index.html#rest_args">rest args</a>.</p>
<div id="prev-next">
<a href="../concurrency_and_parallelism/index.html">&laquo; Concurrency and Parallelism in Clojure</a>
||
<a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../functions/index.html">Functions in Clojure</a></li>
<li><a href="../laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,617 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Clojure interoperability with Java</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/interop/" />
<meta property="og:title" content="Clojure interoperability with Java" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/interop/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Clojure interoperability with Java</h2>
</div>
<p>This guide covers:</p><ul><li>How to instantiate Java classes</li><li>How to invoke Java methods</li><li>How to extend Java classes with proxy</li><li>How to implement Java interfaces with reify</li><li>How to generate Java classes with gen-class</li><li>Other topics related to interop</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5.</p><h2 id="overview">Overview</h2><p>Clojure was designed to be a hosted language that directly interoperates with its host platform (JVM, CLR and so on).
Clojure code is compiled to JVM bytecode. For method calls on Java objects, Clojure compiler
will try to emit the same bytecode <code>javac</code> would produce.</p><p>It is possible to implement interfaces, extend and generate Java classes in Clojure.</p><p>Clojure also provides convenient functions and macros that make consuming of Java libraries
easier and often more concise than it would be in Java code.</p><h2 id="imports">Imports</h2><p>Java classes can be referenced either using their fully-qualified names (FQNs) such as
<code>java.util.Date</code> or be <em>imported</em> in the current Clojure namespace using <code>clojure.core/import</code> and
referenced by short names:</p><pre><code class="clojure">java.util.Date ; ⇒ java.util.Date
</code></pre><pre><code class="clojure">(import java.util.Date)
Date ; ⇒ java.util.Date
</code></pre><p><code>ns</code> macro supports imports, too:</p><pre><code class="clojure">(ns myservice.main
(:import java.util.Date))
</code></pre><p>More about the <code>ns</code> macro can be found in the article on <a href="../namespaces/index.html">Clojure namespaces</a>.</p><p>Dynamic (at runtime) imports are usually only used in the REPL and cases when there are multiple implementations of a particular
protocol/service/feature and it is not possible to tell which one should be used until run time.</p><h3 id="automatic-imports-for-javalang">Automatic Imports For java.lang.*</h3><p>Classes from the <code>java.lang</code> package are automatically imported. For example, you can use <code>String</code> or <code>Math</code>
without explicitly importing them:</p><pre><code class="clojure">(defn http-uri?
[^String uri]
(.startsWith (.toLowerCase uri) "http"))
(Math/round 0.7886)
</code></pre><h3 id="inner-nested-classes">Inner (Nested) Classes</h3><p>In Java, classes can be nested inside other classes. They are called <em>inner classes</em> and by convention,
separated from their outer class by a dollar sign (<code>$</code>):</p><pre><code class="clojure">(import java.util.Map$Entry)
Map$Entry ; ⇒ java.util.Map$Entry
;; this example assumes RabbitMQ Java client is on classpath
(import com.rabbitmq.client.AMQP$BasicProperties)
AMQP$BasicProperties ; ⇒ com.rabbitmq.client.AMQP$BasicProperties
</code></pre><p>Note that if you need to use both a class and one or more of its inner classes, they all need to be imported separately.
As far as JVM is concerned, they are all separate classes, there is no "imports hierarchy".</p><h2 id="how-to-instantiate-java-classes">How to Instantiate Java Classes</h2><p>Java classes are instantiated using the <code>new</code> special form:</p><pre><code class="clojure">(new java.util.Date) ; ⇒ #inst "2012-10-09T21:23:57.278-00:00"
</code></pre><p>However, the Clojure reader provides a bit of syntactic sugar and you are much more likely
to see this:</p><pre><code class="clojure">(java.util.Date.) ; ⇒ #inst "2012-10-09T21:24:43.878-00:00"
</code></pre><p>It is possible to use fully qualified names (e.g. <code>java.util.Date</code>) or short names with imports:</p><pre><code class="clojure">(import java.util.Date)
(Date.) ; ⇒ #inst "2012-10-09T21:24:27.229-00:00"
</code></pre><p>An example with constructor arguments:</p><pre><code class="clojure">(java.net.URI. "http://clojure.org") ; ⇒ #&lt;URI http://clojure.org&gt;
</code></pre><h2 id="how-to-invoke-java-methods">How to Invoke Java Methods</h2><h3 id="instance-methods">Instance Methods</h3><p>Instance methods are invoked using the <code>.</code> special form:</p><pre><code class="clojure">(let [d (java.util.Date.)]
(. d getTime)) ; ⇒ 1349819873183
</code></pre><p>Just like with object instantiation, it is much more common to see an alternative version:</p><pre><code class="clojure">(let [d (java.util.Date.)]
(.getTime d)) ; ⇒ 1349819873183
</code></pre><h3 id="static-methods">Static Methods</h3><p>Static methods can be invoked with the same <code>.</code> special form:</p><pre><code class="clojure">(. Math floor 5.677) ; ⇒ 5.0
</code></pre><p>or (typically) to sugared version, <code>ClassName/methodName</code>:</p><pre><code class="clojure">(Math/floor 5.677) ; ⇒ 5.0
(Boolean/valueOf "false") ; ⇒ false
(Boolean/valueOf "true") ; ⇒ true
</code></pre><h3 id="chained-calls-with-the-double-dot-form">Chained Calls With The Double Dot Form</h3><p>It is possible to chain method calls using the <code>..</code> special form:</p><pre><code class="clojure">(.. (java.util.Date.) getTime toString) ; ⇒ "1349821993809"
</code></pre><h3 id="multiple-calls-on-the-same-object">Multiple Calls On the Same Object</h3><p>If you need to call a bunch of methods on a mutable object, you
can use the <code>doto</code> macro:</p><pre><code class="clojure">(doto (java.util.Stack.)
(.push 42)
(.push 13)
(.push 7)) ; ⇒ #&lt;Stack [42, 13, 7]&gt;
(let [pt (Point. 0 0)]
(doto pt
(.move 10 0))) ; ⇒ #&lt;Point java.awt.Point[x=10, y=0]
(let [pt (Point. 0 0)]
(doto pt
(.move 10 0)
(.translate 0 10))) ; ⇒ #&lt;Point java.awt.point[x=10,y=10]
</code></pre><p>The <code>doto</code> macro returns its first argument as a result.</p><h2 id="how-to-access-java-fields">How to Access Java Fields</h2><p>Public mutable fields are not common in Java libraries but sometimes you need to access them.
It's done with the same dot special form:</p><pre><code class="clojure">(import java.awt.Point)
(let [pt (Point. 0 10)]
(. pt x)) ; ⇒ 0
(let [pt (Point. 0 10)]
(. pt y)) ; ⇒ 10
</code></pre><p>and just like with instance methods, it is much more common to see the following version:</p><pre><code class="clojure">(import java.awt.Point)
(let [pt (Point. 0 10)]
(.x pt)) ; ⇒ 0
(let [pt (Point. 0 10)]
(.y pt)) ; ⇒ 10
</code></pre><h2 id="how-to-set-java-fields">How to Set Java Fields</h2><p>To set a public mutable field, use <code>clojure.core/set!</code> that takes a field in the dot notation
demonstrated earlier and a new value:</p><pre><code class="clojure">(import java.awt.Point)
(let [pt (Point. 0 10)]
(set! (.y pt) 100)
(.y pt)) ; ⇒ 100
</code></pre><p>Fortunately, mutable public fields are rare to meet in the JVM ecosystem so you won't need
to do this often.</p><h2 id="how-to-work-with-enums">How To Work With Enums</h2><p><a href="http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html">Enums (enumeration) type</a> values are accessed
the same way as fields, except on enum classes and not objects:</p><pre><code class="clojure">java.util.concurrent.TimeUnit/MILLISECONDS ; ⇒ #&lt; MILLISECONDS&gt;
</code></pre><h2 id="determining-classes-of-java-objects">Determining Classes of Java Objects</h2><p>To get class of a particular value, pass it to <code>clojure.core/class</code>:</p><pre><code class="clojure">(class 1) ; ⇒ java.lang.Long
(class 1.0) ; ⇒ java.lang.Double
(class "docs") ; ⇒ java.lang.String
(class (java.net.URI. "https://github.com")) ; ⇒ java.net.URI
</code></pre><p>As this example demonstrates, Clojure strings are JVM strings, integer literals are compiled
as longs and floating point literals are compiled as doubles.</p><p>You can also use <code>clojure.core/type</code> to return either the class of the
Java object, or the <code>:type</code> metadata if it exists:</p><pre><code class="clojure">(def foo (with-meta [1 2 3] {:type :bar}))
(type foo)
;; ⇒ :bar
(type [1 2 3])
;; ⇒ clojure.lang.PersistentVector
</code></pre><h2 id="how-to-get-a-java-class-reference-by-name">How To Get a Java Class Reference By Name</h2><p>To obtain a class reference by its string name (fully qualified), use <code>Class/forName</code> via Java interop:</p><pre><code class="clojure">(Class/forName "java.util.Date") ; ⇒ java.util.Date
</code></pre><h3 id="array-types-primitives">Array Types, Primitives</h3><p>JVM has what is called <strong>primitive types</strong> (numerics, chars, booleans) that are not "real" objects.
In addition, array types have pretty obscure internal names. If you need to obtain a reference to
an array of longs, for example, pass <code>"[[J"</code> to <code>Class/forName</code>. Below is the full table:</p><table class="table-striped table-bordered table"><thead><tr><th>Internal JVM class name</th><th>Array of ? (type)</th></tr></thead><tbody><tr><td><pre>"[[S"</pre></td><td>short</td></tr><tr><td><pre>"[[I"</pre></td><td>integer</td></tr><tr><td><pre>"[[J"</pre></td><td>long</td></tr><tr><td><pre>"[[F"</pre></td><td>float</td></tr><tr><td><pre>"[[D"</pre></td><td>double</td></tr><tr><td><pre>"[[B"</pre></td><td>byte</td></tr><tr><td><pre>"[[C"</pre></td><td>char</td></tr><tr><td><pre>"[[Z"</pre></td><td>boolean</td></tr></tbody></table><p>If this does not make much sense, don't worry. Just remember to come
back to this guide when you need to extend a protocol for an array of
primitives.</p><h2 id="implementing-java-interfaces-with-reify">Implementing Java Interfaces With reify</h2><p>It is possible to implement Java interfaces in Clojure. It is
typically needed to interact with Java libraries that take arguments
implementing a particular interface.</p><p>Interfaces are implemented using the <code>reify</code> special form.</p><p>Given the following Java interface:</p><pre><code class="java">public
interface FilenameFilter {
/**
* Tests if a specified file should be included in a file list.
*
* @param dir the directory in which the file was found.
* @param name the name of the file.
* @return &lt;code&gt;true&lt;/code&gt; if and only if the name should be
* included in the file list; &lt;code&gt;false&lt;/code&gt; otherwise.
*/
boolean accept(File dir, String name);
}
</code></pre><p>here is how to implement it in Clojure:</p><pre><code class="clojure">;; a FileFilter implementation that accepts everything
(reify java.io.FilenameFilter
(accept [this dir name]
true))
</code></pre><p><code>reify</code> takes an interface (fully-qualified name or short name) and one or more
method implementations that mimic function definitions without the <code>defn</code> and with
<em>this</em> (as in Java, JavaScript or <em>self</em> in Ruby, Python) reference being the first argument:</p><pre><code class="clojure">(accept [this dir name]
true)
</code></pre><p>With <code>reify</code>, generally there is no need to add type hints on arguments: Clojure
compiler typically will detect the best matching method (by name and number of arguments).</p><p><code>reify</code> returns a <em>Java class instance</em>. Clojure compiler will generate a class that implements
the interface and instantiate it. To demonstrate that reified objects indeed implement
the interface:</p><pre><code class="clojure">(let [ff (reify java.io.FilenameFilter
(accept [this dir name]
true))]
(instance? java.io.FileFilter ff)) ; ⇒ true
</code></pre><p><code>reify</code> can be used to implement multiple interfaces at once:</p><pre><code class="clojure">(let [ff (reify java.io.FilenameFilter
(accept [this dir name]
true)
java.io.FileFilter
(accept [this dir]
true))]
(instance? java.io.FileFilter ff)) ; ⇒ true
</code></pre><h3 id="reify-parameter-destructuring-and-varargs">reify, Parameter Destructuring and Varargs</h3><p><code>reify</code> does not support destructuring or variadic number of arguments in method signatures.
For example, the following will not work and won't even compile in Clojure 1.5:</p><pre><code class="clojure">(reify com.megacorp.api.AnInterface
(aMethod [a [b c]]
(comment ...))
(anotherMethod [a &amp; rest]
(comment ...)))
</code></pre><h3 id="example-1">Example 1</h3><p>The following example demonstrates how instances created with <code>reify</code> are passed around
as regular Java objects:</p><pre><code class="clojure">(import java.io.File)
;; a file filter implementation that keeps only .clj files
(let [ff (reify java.io.FilenameFilter
(accept [this dir name]
(.endsWith name ".clj")))
dir (File. "/Users/antares/Development/ClojureWerkz/neocons.git/")]
(into [] (.listFiles dir ff)))
;; ⇒ [#&lt;File /Users/antares/Development/ClojureWerkz/neocons.git/project.clj&gt;]
</code></pre><p><code>reify</code> forms a closure: it will capture locals in its scope. This can be used to make implemented
methods delegate to Clojure functions. The same example, rewritten with delegation:</p><pre><code class="clojure">user&gt; (import java.io.File)
;; a file filter implementation that keeps only .clj files
(let [f (fn [^File dir ^String name]
(.endsWith name ".clj"))
ff (reify java.io.FilenameFilter
(accept [this dir name]
(f dir name)))
dir (File. "/Users/antares/Development/ClojureWerkz/neocons.git/")]
(into [] (.listFiles dir ff)))
;; ⇒ [#&lt;File /Users/antares/Development/ClojureWerkz/neocons.git/project.clj&gt;]
</code></pre><p>Note that unlike in the "inline" implementation, Clojure compiler cannot infer types of
<code>dir</code> and <code>name</code> parameters in the function that does the filtering, so we added type hints
to avoid reflective calls. When methods are implemented "inline", types can be inferred from
method signatures in the interface.</p><h2 id="extending-java-classes-with-proxy">Extending Java Classes With proxy</h2><p><code>proxy</code> is one of two ways to generate instances of anonymous classes in Clojure.
<code>proxy</code> takes two vectors: one listing its superclass and (optional) interfaces, another constructor signatures, as well as
method implementations. Method implementations are basically identical to <code>reify</code> except that the <code>this</code> argument is
not necessary.</p><p>A very minimalistic example, we instantiate an anonymous class that extends <code>java.lang.Object</code>, implements no
interfaces, has no explictly defined constructors and overrides <code>#toString</code>:</p><pre><code class="clojure">(proxy [Object] []
(toString []
"I am an instance of an anonymous class generated via proxy"))
;; ⇒ #&lt;Object$0 I am an instance of an anonymous class generated via proxy&gt;
</code></pre><p>Clojure compiler will generate an anonymous class for this <code>proxy</code> and at runtime, the cost of
a <code>proxy</code> call is the cost of instantiating this class (the class is not generated anew on every single call).</p><p>A slightly more complex example where the generated class also implements <code>java.lang.Runnable</code> (runnable objects
are commonly used with threads and <code>java.util.concurrent</code> classes) which defines one method, <code>#run</code>:</p><pre><code class="clojure">;; extends java.lang.Object, implements java.lang.Runnable
(let [runnable (proxy [Object Runnable] []
(toString []
"I am an instance of an anonymous class generated via proxy")
(run []
(println "Run, proxy, run")))]
(.run runnable)) ; ⇒ nil
;; outputs "Run, proxy, run"
</code></pre><p><code>proxy</code> forms a closure: it will capture locals in its scope. This is very often used to create an instance
that delegates to a Clojure function:</p><pre><code class="clojure">(let [f (fn [] (println "Executed from a function"))
obj (proxy [Object Runnable] []
(run []
(f)))]
(.run obj)) ; ⇒ nil
;; outputs "Executed from a function"
</code></pre><p>TBD: more realistic examples | <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></p><h2 id="clojure-functions-implement-runnable-and-callable">Clojure Functions Implement Runnable and Callable</h2><p>Note that Clojure functions implement <code>java.lang.Runnable</code> and
<code>java.util.concurrent.Callable</code> directly so you can pass functions to
methods found in various classes from the <code>java.util.concurrent</code> package.</p><p>For example, to run a function in a new thread:</p><pre><code class="clojure">(let [t (Thread. (fn []
(println "I am running in a separate thread")))]
(.start t))
</code></pre><p>Or submit a function for execution to a thread pool (in JDK terms: an execution service):</p><pre><code class="clojure">(import '[java.util.concurrent Executors ExecutorService Callable])
(let [^ExecutorService pool (Executors/newFixedThreadPool 16)
^Callable clbl (cast Callable (fn []
(reduce + (range 0 10000))))
task (.submit pool clbl)]
(.get task))
;; ⇒ 49995000
</code></pre><p>Note that without the cast, Clojure compiler would not be able to determine
which exact version of the method we intend to invoke, because <code>java.util.concurrent.ExecutionService/submit</code>
has two versions, one for <code>Runnable</code> and one for <code>Callable</code>. They work very much the same but return
slightly different results (<code>Callable</code> produces a value while <code>Runnable</code> always returns nil when
executed).</p><p>The exception we would get without the cast is</p><pre><code>CompilerException java.lang.IllegalArgumentException: More than one matching method found: submit, compiling:(NO_SOURCE_PATH:2)
</code></pre><h2 id="gen-class-and-how-to-implement-java-classes-in-clojure">gen-class and How to Implement Java Classes in Clojure</h2><h3 id="overview-1">Overview</h3><p><code>gen-class</code> is a Clojure feature for implementing Java classes in Clojure. It is relatively
rarely used compared to <code>proxy</code> and <code>reify</code> but is needed to implement executable classes
(that <code>java</code> runner and IDEs can as program entry points).</p><p>Unlike <code>proxy</code> and <code>reify</code>, <code>gen-class</code> defines named classes. They can be passed to Java
APIs that expect class references. Classes defined with <code>gen-class</code> can extend
base classes, implement any number of Java interfaces, define any number of constructors
and define both instance and static methods.</p><h3 id="aot">AOT</h3><p><code>gen-class</code> requires <em>ahead-of-time</em> (AOT) compilation. It means that
before using the classes defined with <code>gen-class</code>, the Clojure
compiler needs to produce <code>.class</code> files from <code>gen-class</code> definitions.</p><h3 id="class-definition-with-clojurecoregen-class">Class Definition With clojure.core/gen-class</h3><p><code>clojure.core/gen-class</code> is a macro that uses a DSL for defining class
methods, base class, implemented interfaces and so on.</p><p>It takes a number of options:</p><ul><li><code>:name</code> (a symbol): defines generated class name</li><li><code>:extends</code> (a symbol): name of the base class</li><li><code>:implements</code> (a collection): interfaces the class implements</li><li><code>:constructors</code> (a map): constructor signatures</li><li><code>:methods</code> (a collection): lists methods that will be implemented</li><li><code>:init</code> (symbol): defines a function that will be invoked with constructor arguments</li><li><code>:post-init</code> (symbol): defines a function that will be called with a constructed instance as its first argument</li><li><code>:state</code> (symbol): if supplied, a public final instance field with the given name will be created. Only makes sense when
used with <code>:init</code>. State field value should be an atom or other ref type to allow state mutation.</li><li><code>:prefix</code> (string, default: <code>"-"</code>): methods will call functions named as <code>(str prefix method-name)</code>, e.g. <code>-getName</code> for <code>getName</code>.</li><li><code>:main</code> (boolean): if <code>true</code>, a public static main method will be generated for the class. It will delegate
to a function named main with the prefix (<code>(str prefix "main")</code>), <code>-main</code> by default</li><li><code>:exposes</code>: TBD</li><li><code>:exposes-methods</code>: TBD</li><li><code>:factory</code>: TBD</li><li><code>:load-impl-ns</code>: TBD</li><li><code>:impl-ns</code>: TBD</li></ul><h4 id="the-name-option">The :name Option</h4><p>TBD</p><h4 id="the-extends-option">The :extends Option</h4><p>TBD</p><h4 id="the-implements-option">The :implements Option</h4><p>TBD</p><h4 id="the-constructors-option">The :constructors Option</h4><p>TBD</p><h4 id="the-methods-option">The :methods Option</h4><p>TBD</p><h4 id="the-init-option">The :init Option</h4><p>TBD</p><h4 id="the-post-init-option">The :post-init Option</h4><p>TBD</p><h4 id="the-state-option">The :state Option</h4><p>TBD</p><h4 id="the-prefix-option">The :prefix Option</h4><p>TBD</p><h4 id="the-main-option">The :main Option</h4><p>TBD</p><h4 id="the-exposes-option">The :exposes Option</h4><p>TBD</p><h4 id="the-exposes-methods-option">The :exposes-methods Option</h4><p>TBD</p><h4 id="the-factory-option">The :factory Option</h4><p>TBD</p><h4 id="the-load-impl-ns-option">The :load-impl-ns Option</h4><p>TBD</p><h4 id="the-impl-ns-option">The :impl-ns Option</h4><p>TBD</p><h3 id="gen-class-in-the-ns-macro">gen-class In The ns Macro</h3><p><code>gen-class</code> can be used with existing namespaces by adding <code>(:gen-class)</code> to the
<code>ns</code> macro. Here is a "hello, world" example command line app that uses <code>gen-class</code>
to generate a class that JVM launcher (<code>java</code>) can run:</p><pre><code class="clojure">(ns genclassy.core
(:gen-class))
(defn -main
[&amp; args]
(println "Hello, World!"))
</code></pre><p>This will use the name of the namespace for class name and use the namespace for method
implementation (see the <code>:impl-ns</code> option above).</p><h3 id="examples">Examples</h3><p>A medium size example taken from an open source library:</p><pre><code class="clojure">(ns clojurewerkz.quartzite.listeners.amqp.PublishingSchedulerListener
(:gen-class :implements [org.quartz.SchedulerListener]
:init init
:state state
:constructors {[com.rabbitmq.client.Channel String String] []})
(:require [langohr.basic :as lhb]
[clojure.data.json :as json])
(:use [clojurewerkz.quartzite.conversion])
(:import [org.quartz SchedulerListener SchedulerException Trigger TriggerKey JobDetail JobKey]
[com.rabbitmq.client Channel]
[java.util Date]
[clojurewerkz.quartzite.listeners.amqp PublishingSchedulerListener]))
(defn publish
[^PublishingSchedulerListener this payload ^String type]
(let [{ :keys [channel exchange routing-key] } @(.state this)
payload (json/json-str payload)]
(lhb/publish channel exchange routing-key payload :type type)))
(defn -init
[^Channel ch ^String exchange ^String routing-key]
[[] (atom { :channel ch :exchange exchange :routing-key routing-key })])
(defmacro payloadless-publisher
[method-name message-type]
`(defn ~method-name
[this#]
(publish this# (json/json-str {}) ~message-type)))
(payloadless-publisher -schedulerStarted "quartz.scheduler.started")
(payloadless-publisher -schedulerInStandbyMode "quartz.scheduler.standby")
(payloadless-publisher -schedulingDataCleared "quartz.scheduler.cleared")
(payloadless-publisher -schedulerShuttingDown "quartz.scheduler.shutdown")
(defn -schedulerError
[this ^String msg ^SchedulerException cause]
(publish this (json/json-str { :message msg :cause (str cause) }) "quartz.scheduler.error"))
(defn -jobScheduled
[this ^Trigger trigger]
(publish this (json/json-str { :group (-&gt; trigger .getKey .getGroup) :key (-&gt; trigger .getKey .getName) :description (.getDescription trigger) }) "quartz.scheduler.job-scheduled"))
(defn -jobUnscheduled
[this ^TriggerKey key]
(publish this (json/json-str { :group (.getGroup key) :key (.getName key) }) "quartz.scheduler.job-unscheduled"))
(defn -triggerFinalized
[this ^Trigger trigger]
(publish this (json/json-str { :group (-&gt; trigger .getKey .getGroup) :key (-&gt; trigger .getKey .getName) :description (.getDescription trigger) }) "quartz.scheduler.trigger-finalized"))
(defn -triggerPaused
[this ^TriggerKey key]
(publish this (json/json-str { :group (.getGroup key) :key (.getName key) }) "quartz.scheduler.trigger-paused"))
(defn -triggersPaused
[this ^String trigger-group]
(publish this (json/json-str { :group trigger-group }) "quartz.scheduler.triggers-paused"))
(defn -triggerResumed
[this ^TriggerKey key]
(publish this (json/json-str { :group (.getGroup key) :key (.getName key) }) "quartz.scheduler.trigger-resumed"))
(defn -triggersResumed
[this ^String trigger-group]
(publish this (json/json-str { :group trigger-group }) "quartz.scheduler.triggers-resumed"))
(defn -jobAdded
[this ^JobDetail detail]
(publish this (json/json-str { :job-detail (from-job-data (.getJobDataMap detail)) :description (.getDescription detail) }) "quartz.scheduler.job-added"))
(defn -jobDeleted
[this ^JobKey key]
(publish this (json/json-str { :group (.getGroup key) :key (.getName key) }) "quartz.scheduler.job-deleted"))
(defn -jobPaused
[this ^JobKey key]
(publish this (json/json-str { :group (.getGroup key) :key (.getName key) }) "quartz.scheduler.job-paused"))
(defn -jobsPaused
[this ^String job-group]
(publish this (json/json-str { :group job-group }) "quartz.scheduler.jobs-paused"))
(defn -jobResumed
[this ^JobKey key]
(publish this (json/json-str { :group (.getGroup key) :key (.getName key) }) "quartz.scheduler.job-resumed"))
(defn -jobsResumed
[this ^String job-group]
(publish this (json/json-str { :group job-group }) "quartz.scheduler.jobs-resumed"))
</code></pre><h3 id="inspecting-class-signatures">Inspecting Class Signatures</h3><p>When using <code>gen-class</code> for interoperability purposes, sometimes it is necessary to inspect the API
of the class generated by <code>gen-class</code>.</p><p>It can be inspected
using <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javap.html">javap</a>. Given the
following Clojure namespace:</p><pre><code class="clojure">(ns genclassy.core
(:gen-class))
(defn -main
[&amp; args]
(println "Hello, World!"))
</code></pre><p>We can inspect the produced class like so:</p><pre><code># from target/classes, default .class files location used by Leiningen
javap genclassy.core
</code></pre><p>will output</p><pre><code class="java">public class genclassy.core {
public static {};
public genclassy.core();
public java.lang.Object clone();
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public static void main(java.lang.String[]);
}
</code></pre><h2 id="how-to-extend-protocols-to-java-classes">How To Extend Protocols to Java Classes</h2><p>Clojure protocols can be extended to any java class (including
Clojure's internal types) very easily using <code>extend</code>:</p><p>Using the example of a json library, we can define our goal as getting
to the point where the following works:</p><pre><code class="clojure">(json-encode (java.util.UUID/randomUUID))
</code></pre><p>First, let's start with the protocol for json encoding an object:</p><pre><code class="clojure">(defprotocol JSONable
(json-encode [obj]))
</code></pre><p>So, everything that is "JSONable" implements a <code>json-encode</code> method.</p><p>Next, let's define a dummy method to do the "encoding" (in this
example, it just prints to standard out instead, it doesn't actually
do any json encoding):</p><pre><code class="clojure">(defn encode-fn
[x]
(prn x))
</code></pre><p>Now, define a method that will encode java objects by calling <code>bean</code>
on them, then making each value of the bean map a string:</p><pre><code class="clojure">(defn encode-java-thing
[obj]
(encode-fn
(into {}
(map (fn [m]
[(key m) (str (val m))])
(bean obj)))))
</code></pre><p>Let's try it on an example object, a UUID:</p><pre><code class="clojure">(encode-java-thing (java.util.UUID/randomUUID))
;; ⇒ {:mostSignificantBits "-6060053801408705927",
;; :leastSignificantBits "-7978739947533933755",
;; :class "class java.util.UUID"}
</code></pre><p>The next step is to extend the protocol to the java type, telling
clojure which java type to extend, the protocol to implement and the
method to use for the <code>json-encode</code> method:</p><pre><code class="clojure">(extend java.util.UUID
JSONable
{:json-encode encode-java-thing})
</code></pre><p>Alternatively, you could use the <code>extend-type</code> macro, which actually
expands into calls to <code>extend</code>:</p><pre><code class="clojure">(extend-type java.util.UUID
JSONable
(json-encode [obj] (encode-java-thing obj)))
</code></pre><p>Now we can use <code>json-encode</code> for the object we've extended:</p><pre><code class="clojure">(json-encode (java.util.UUID/randomUUID))
;; ⇒ {:mostSignificantBits "3097485598740136901",
;; :leastSignificantBits "-9000234678473924364",
;; :class "class java.util.UUID"}
</code></pre><p>You could also write the function inline in the extend block, for
example, extending <code>nil</code> to return a warning string:</p><pre><code class="clojure">(extend nil
JSONable
{:json-encode (fn [x] "x is nil!")})
(json-encode nil)
;; ⇒ "x is nil!"
</code></pre><p>The <code>encode-java-thing</code> method can also be reused for other Java types
we may want to encode:</p><pre><code class="clojure">(extend java.net.URL
JSONable
{:json-encode encode-java-thing})
(json-encode (java.net.URL. "http://aoeu.com"))
;; ⇒ {:path "",
;; :protocol "http",
;; :authority "aoeu.com",
;; :host "aoeu.com",
;; :ref "",
;; :content "sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@4ecac02f",
;; :class "class java.net.URL",
;; :defaultPort "80",
;; :port "-1",
;; :query "",
;; :file "",
;; :userInfo ""}
</code></pre><h2 id="using-intrinsic-locks-synchronized-in-clojure">Using Intrinsic Locks ("synchronized") in Clojure</h2><p>Every object on the JVM has an <em>intrinsic lock</em> (also referred to as <em>monitor lock</em>
or simply <em>monitor</em>). While very rarely necessary, Clojure provides support for
operations that acquire intrinsic lock of a mutable Java object.</p><p>This is covered in the <a href="../concurrency_and_parallelism/index.html#using_intrinsic_locks_synchronized_in_clojure">Concurrency and Parallelism guide</a>.</p><h2 id="wrapping-up">Wrapping Up</h2><p>TBD: <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></p><h2 id="contributors">Contributors</h2><p>Michael Klishin <a href="mailto:michael@defprotocol.org">michael@defprotocol.org</a> (original author)
Lee Hinman <a href="mailto:lee@writequit.org">lee@writequit.org</a>
gsnewmark <a href="mailto:gsnewmark@meta.ua">gsnewmark@meta.ua</a></p>
<div id="prev-next">
<a href="../laziness/index.html">&laquo; Laziness in Clojure</a>
||
<a href="../macros/index.html">Clojure Macros and Metaprogramming &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../functions/index.html">Functions in Clojure</a></li>
<li><a href="../laziness/index.html">Laziness in Clojure</a></li>
<li><a href="index.html">Clojure interoperability with Java</a></li>
<li><a href="../macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,264 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Laziness in Clojure</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/laziness/" />
<meta property="og:title" content="Laziness in Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/laziness/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Laziness in Clojure</h2>
</div>
<p>This guide covers:</p><ul><li>What are lazy sequences</li><li>Pitfalls with lazy sequences</li><li>How to create functions that produce lazy sequences</li><li>How to force evaluation</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5.</p><h2 id="overview">Overview</h2><p>Clojure is not a <a href="http://en.wikipedia.org/wiki/Lazy_evaluation">lazy language</a>.</p><p>However, Clojure supports <em>lazily evaluated sequences</em>. This means that sequence elements are not
available ahead of time and produced as the result of a computation. The computation
is performed as needed. Evaluation of lazy sequences is known as <em>realization</em>.</p><p>Lazy sequences can be infinite (e.g. the sequence of Fibonacci numbers, a sequence of
dates with a particular interval between them, and so on). If a lazy sequence is finite,
when its computation is completed, it becomes <em>fully realized</em>.</p><p>When it is necessary to fully realize a lazy sequence, Clojure provides a way to
<em>force evaluation</em> (force realization).</p><h2 id="benefits-of-lazy-sequences">Benefits of Lazy Sequences</h2><p>Lazy sequences have two main benefits:</p><ul><li>They can be infinite</li><li>Full realization of interim results can be avoided</li></ul><h2 id="producing-lazy-sequences">Producing Lazy Sequences</h2><p>Lazy sequences are produced by functions. Such functions either use the <code>clojure.core/lazy-seq</code> macro
or other functions that produce lazy sequences.</p><p><code>clojure.core/lazy-seq</code> accepts one or more forms that produce a sequence of <code>nil</code> (when the sequence
is fully realized) and returns a seqable data structure that invokes the body the first time
the value is needed and then caches the result.</p><p>For example, the following function produces a lazy sequence of random UUIDs strings:</p><pre><code class="klipse-clojure nohighlight">(defn uuid-seq
[]
(lazy-seq
(cons (str (random-uuid))
(uuid-seq))))
</code></pre><blockquote><p>Note: the <code>random-uuid</code> function is available in ClojureScript and was introduced into Clojure
in version 1.11 Alpha 3. Prior to that, you needed to use Java interop:</p></blockquote><pre><code class="clojure">(defn uuid-seq
[]
(lazy-seq
(cons (str (java.util.UUID/randomUUID))
(uuid-seq))))
</code></pre><p>Another example:</p><pre><code class="klipse-clojure nohighlight">(defn fib-seq
"Returns a lazy sequence of Fibonacci numbers"
([]
(fib-seq 0 1))
([a b]
(lazy-seq
(cons b (fib-seq b (+ a b))))))
</code></pre><p>Both examples use <code>clojure.core/cons</code> which prepends an element to a sequence. The sequence
can in turn be lazy, which both of the examples rely on.</p><p>Even though both of these sequences are infinite, taking first N elements from each does
return successfully:</p><pre><code class="klipse-clojure nohighlight">(take 3 (uuid-seq))
</code></pre><pre><code class="klipse-clojure nohighlight">(take 10 (fib-seq))
</code></pre><pre><code class="klipse-clojure nohighlight">(take 20 (fib-seq))
</code></pre><h2 id="realizing-lazy-sequences-forcing-evaluation">Realizing Lazy Sequences (Forcing Evaluation)</h2><p>Lazy sequences can be forcefully realized with <code>clojure.core/dorun</code> and
<code>clojure.core/doall</code>. The difference between the two is that <code>dorun</code>
throws away all results and is supposed to be used for side effects,
while <code>doall</code> returns computed values:</p><pre><code class="klipse-clojure nohighlight">(dorun (map inc [1 2 3 4]))
</code></pre><pre><code class="klipse-clojure nohighlight">(doall (map inc [1 2 3 4]))
</code></pre><h2 id="commonly-used-functions-that-produce-lazy-sequences">Commonly Used Functions That Produce Lazy Sequences</h2><p>Multiple frequently used <code>clojure.core</code> functions return lazy sequences,
most notably:</p><ul><li><code>map</code></li><li><code>filter</code></li><li><code>remove</code></li><li><code>range</code></li><li><code>take</code></li><li><code>take-while</code></li><li><code>drop</code></li><li><code>drop-while</code></li></ul><p>The following example uses several of these functions to return 10 first
even numbers in the range of [0, n):</p><pre><code class="klipse-clojure nohighlight">(take 10 (filter even? (range 0 100)))
</code></pre><p>Several functions in <code>clojure.core</code> are designed to produce lazy
sequences:</p><ul><li><code>repeat</code></li><li><code>iterate</code></li><li><code>cycle</code></li></ul><p>For example:</p><pre><code class="klipse-clojure nohighlight">(take 3 (repeat "ha"))
</code></pre><pre><code class="klipse-clojure nohighlight">(take 5 (repeat "ha"))
</code></pre><pre><code class="klipse-clojure nohighlight">(take 3 (cycle [1 2 3 4 5]))
</code></pre><pre><code class="klipse-clojure nohighlight">(take 10 (cycle [1 2 3 4 5]))
</code></pre><pre><code class="klipse-clojure nohighlight">(take 3 (iterate (partial + 1) 1))
</code></pre><pre><code class="klipse-clojure nohighlight">(take 5 (iterate (partial + 1) 1))
</code></pre><h2 id="lazy-sequences-chunking">Lazy Sequences Chunking</h2><p>There are two fundamental strategies for implementing lazy sequences:</p><ul><li>Realize elements one-by-one</li><li>Realize elements in groups (chunks, batches)</li></ul><p>In Clojure 1.1+, lazy sequences are <em>chunked</em> (realized in chunks).</p><p>For example, in the following code</p><pre><code class="klipse-clojure nohighlight">(take 10 (range 1 1000000000000))
</code></pre><p>one-by-one realization would realize one element 10 times. With chunked sequences,
elements are realized ahead of time in chunks (32 elements at a time).</p><p>This reduces the number of realizations and, for many common workloads, improves
efficiency of lazy sequences.</p><h2 id="contributors">Contributors</h2><p>Michael Klishin <a href="mailto:michael@defprotocol.org">michael@defprotocol.org</a>, 2013 (original author)</p>
<div id="prev-next">
<a href="../functions/index.html">&laquo; Functions in Clojure</a>
||
<a href="../interop/index.html">Clojure interoperability with Java &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../functions/index.html">Functions in Clojure</a></li>
<li><a href="index.html">Laziness in Clojure</a></li>
<li><a href="../interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
<link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">
<script>
window.klipse_settings = {
"selector" : ".klipse-clojure"
};
</script>
<script src="https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"></script>
</body>
</html>

View file

@ -0,0 +1,382 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Clojure Macros and Metaprogramming</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/macros/" />
<meta property="og:title" content="Clojure Macros and Metaprogramming" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/macros/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Clojure Macros and Metaprogramming</h2>
</div>
<p>This guide covers:</p><ul><li>Clojure macros</li><li>the Clojure compilation process</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5.</p><h2 id="before-you-read-this-guide">Before You Read This Guide</h2><p>This is one of the most hardcore guides of the entire Clojure documentation
project. It describes concepts that are relatively unique to the Lisp family of languages
that Clojure belongs to. Understanding them may take some time for folks without
a metaprogramming background. Don't let this learning curve
discourage you.</p><p>If some parts are not clear, please ask for clarification <a href="https://groups.google.com/forum/?fromgroups#!forum/clojure">on the
mailing
list</a> or
<a href="https://github.com/clojure-doc/clojure-doc.github.io/issues">file an issue</a> on GitHub.
We will work hard on making this guide easy to follow with edits and
images to illustrate the concepts.</p><h2 id="overview">Overview</h2><p>Clojure is a dialect of Lisp and while it departs with some features of "traditional" Lisps,
the fundamentals are there. One very powerful feature that comes with it is <em>macros</em>,
a way to do metaprogramming using the language itself. This is pretty different from
other languages known for good metaprogramming capabilities (e.g. Ruby) in that
in Clojure, metaprogramming does not mean string generation. Instead, it means
constructing a tree [of S-expressions, or lists]. This enables very powerful
DSLs (domain-specific languages).</p><h2 id="compile-time-and-run-time">Compile Time and Run Time</h2><p>Clojure is a compiled language. The compiler reads source files or strings,
produces data structures (aka the AST) and performs <em>macroexpansion</em>. Macros are evaluated at
<em>compile time</em> and produce modified data structures that are compiled to the JVM
bytecode. That bytecode is executed at <em>run time</em>.</p><p>Clojure code is compiled when it is loaded with <code>clojure.core/load</code> or <code>clojure.core/require</code>
or can be ahead of time (AOT compilation) using tools such as <a href="http://leiningen.org">Leiningen</a>
or the <a href="../../ecosystem/maven/index.html">Clojure Maven plugin</a>.</p><h2 id="clojure-reader">Clojure Reader</h2><p>Reader is another name for parser. Unlike many other languages, reader in Clojure
can be extended in the language itself. It is also exposed to the language
with <code>clojure.core/read</code> and <code>clojure.core/read-string</code> functions that
return data structures:</p><pre style="visibility:hidden; height:0;"><code class="klipse-clojure nohighlight">
(require '[cljs.reader :refer [read-string]])
</code></pre><pre><code class="klipse-clojure nohighlight">(read-string "(if true :truth :false)")
;= (if true :truth :false)
</code></pre><p>Here we got back a list that is not evaluated.</p><p>The Reader produces data structures (in part that's why "code is data" in homoiconic
languages) that are then evaluated:</p><ul><li>Literals (e.g., strings, integers, vectors) evaluate to themselves</li><li>Lists evaluate to invocations (calls) of functions and so on</li><li>Symbols are resolved to a var value</li></ul><p>Expressions that can be evaluated (invoked) are known as <em>forms</em>. Forms consist of:</p><ul><li>Functions</li><li>Macros</li><li>Special forms</li></ul><h3 id="special-forms">Special Forms</h3><p>The reader parses some forms in special ways that are not consistent
with the rest of Clojure's syntax.</p><p>Such forms are called <em>special forms</em>. They consist of</p><ul><li>. (the dot special form)</li><li>new</li><li>set!</li><li>def</li><li>var</li><li>fn* (<code>fn</code> without destructuring)</li><li>if</li><li>case* (internal implementation of <code>case</code>)</li><li>do</li><li>let* (<code>let</code> without destructuring)</li><li>letfn* (<code>letfn</code> without destructuring)</li><li>clojure.core/import* (<code>import</code>)</li><li>quote</li><li>loop* (<code>loop</code> without destructuring)</li><li>recur</li><li>throw, try, catch, finally</li><li>deftype* (internals of <code>deftype</code>)</li><li>reify* (internals of <code>reify</code>)</li><li>monitor-enter, monitor-exit</li></ul><p>Some special forms are used directly in user code (like <code>do</code> and <code>if</code>), while others
are only used to build more user friendly interfaces (like using <code>deftype</code> over the special form <code>deftype*</code>).</p><h2 id="first-taste-of-macros">First Taste of Macros</h2><p>Some programming languages include an <code>unless</code> expression (or statement) that is
the opposite of <code>if</code>. Clojure is not one of them but it can be added by using
a macro:</p><pre style="visibility:hidden; height:0;"><code class="klipse-clojure nohighlight">
(require '[chivorcam.core :refer [defmacro defmacfn]])
</code></pre><pre><code class="klipse-clojure nohighlight">(defmacro unless
"Similar to if but negates the condition"
[condition &amp; forms]
`(if (not ~condition)
~@forms))
</code></pre><p>Macros are defined using the <code>clojure.core/defmacro</code> function that takes
macro name as a symbol, an optional documentation string, a vector
of arguments and the macro body.</p><p>This macro can be used like similarly to the <code>if</code> form:</p><pre><code class="klipse-clojure nohighlight">(unless (= 1 2)
"one does not equal two"
"one equals two. How come?")
</code></pre><p>Just like the <code>if</code> special form, this macro produces an expression that
returns a value:</p><pre><code class="clojure">(unless (= 1 2)
"one does not equal two"
"one equals two. How come?")
</code></pre><p>in fact, this is because the macro piggybacks on the <code>if</code> form.
To see what the macro expands to, we can use <code>clojure.core/macroexpand-1</code>:</p><pre><code class="klipse-clojure nohighlight">(macroexpand-1 '(unless (= 1 2) true false))
;= (if (clojure.core/not (= 1 2)) true false)
</code></pre><p>This simplistic macro and the way we expanded it with <code>macroexpand-1</code>
demonstrates three features of the Clojure reader that are used when
writing macros:</p><ul><li>Quote (')</li><li>Syntax quote (`)</li><li>Unquote (~)</li><li>Unquote splicing (~@)</li></ul><h2 id="quote">Quote</h2><p>Quote supresses evaluation of the form that follows it. In other words,
instead of being treated as an invocation, it will be treated as a list.</p><p>Compare:</p><pre><code class="klipse-clojure nohighlight">;; this form is evaluated by calling the clojure.core/+ function
(+ 1 2 3)
;= 6
</code></pre><pre><code class="klipse-clojure nohighlight">;; quote supresses evaluation so the + is treated as a regular
;; list element
'(+ 1 2 3)
;= (+ 1 2 3)
</code></pre><p>The syntax quote supresses evaluation of the form that follows it and
all nested forms. It is similar to templating languages where parts
of the template are "fixed" and parts are "inserted" (evaluated).
The syntax quote makes the form that follows it "a template".</p><h2 id="unquote">Unquote</h2><p>Unquote then is how parts of the template are forced to be evaluated
(act similarly to variables in templates in templating languages).</p><p>Let's take another look at the same <code>unless</code> macro:</p><pre><code class="klipse-clojure nohighlight">(defmacro unless
[condition &amp; forms]
`(if (not ~condition)
~@forms))
</code></pre><p>and how we invoke it:</p><pre><code class="klipse-clojure nohighlight">(unless (= 1 2)
"one does not equal two"
"one equals two. How come?")
</code></pre><p>When the macro is expanded, the condition local in this example has the value
of <code>(= 1 2)</code> (a list). We want <code>unless</code> to perform boolean evaluation on it,
and that's what unquote (<code>~</code>) does as can be seen from macroexpansion:</p><pre><code class="klipse-clojure nohighlight">(macroexpand-1 '(unless (= 1 2) true false))
;= (if (clojure.core/not (= 1 2)) true false)
</code></pre><p>Compare this with what the macro expands to when the unquote is removed:</p><pre><code class="klipse-clojure nohighlight">;; incorrect, missing unquote!
(defmacro unless
[condition &amp; forms]
`(if (not condition)
~@forms))
(macroexpand-1 '(unless (= 1 2) true false))
;= (if (clojure.core/not user/condition) true false)
</code></pre><h3 id="implementation-details">Implementation Details</h3><p>The unquote operator is replaced by the reader with a call to a core
Clojure function, <code>clojure.core/unquote</code>.</p><h2 id="unquote-splicing">Unquote-splicing</h2><p>Some macros take multiple forms. This is common in DSLs, for example.
Each of those forms is often need to be quoted and concatenated.</p><p>The unquote-splicing operator (<code>~@</code>) is a convenient way to do it:</p><pre><code class="klipse-clojure nohighlight">(defmacro unsplice
[&amp; coll]
`(do ~@coll))
</code></pre><pre><code class="klipse-clojure nohighlight">(macroexpand-1 '(unsplice (def a 1) (def b 2)))
;= (do (def a 1) (def b 2))
</code></pre><pre><code class="klipse-clojure nohighlight">(unsplice (def a 1) (def b 2))
;= #'user/b
</code></pre><pre><code class="klipse-clojure nohighlight">a
;= 1
</code></pre><pre><code class="klipse-clojure nohighlight">b
;= 2
</code></pre><h3 id="implementation-details-1">Implementation Details</h3><p>The unquote-splicing operator is replaced by the reader with a call to a core
Clojure function, <code>clojure.core/unquote-splicing</code>.</p><h2 id="macro-hygiene-and-gensym">Macro Hygiene and gensym</h2><p>When writing a macro, there is a possibility that the macro will interact with
vars or locals outside of it in unexpected ways, for example, by <a href="http://en.wikipedia.org/wiki/Variable_shadowing">shadowing</a> them.
Such macros are known as <em>unhygienic macros</em>.</p><p>Clojure does not implement a full solution to hygienic macros but
provides solutions to the biggest pitfalls of unhygienic macros by enforcing several restrictions:</p><ul><li>Symbols within a syntax quoted form are namespace-qualified</li><li>Unique symbol name generation (aka <em>gensyms</em>)</li></ul><h3 id="namespace-qualification-within-syntax-quote">Namespace Qualification Within Syntax Quote</h3><p>To demonstrate this behavior of syntax quote, consider the following example
that replaces values "yes" and "no" with true and false, respectively, at compile
time:</p><pre><code class="klipse-clojure nohighlight">(defmacro yes-no-&gt;boolean
[val]
`(let [b (= ~val "yes")]
b))
;= #'user/yes-no-&gt;boolean
</code></pre><pre><code class="klipse-clojure nohighlight">(macroexpand-1 '(yes-no-&gt;boolean "yes"))
;= (clojure.core/let [user/b (clojure.core/= "yes" "yes")] user/b)
</code></pre><p>Macroexpansion demonstrates that the Clojure compiler makes the <code>b</code> symbol namespace-qualified
(<code>user</code> is the default namespace in the Clojure REPL). This helps avoid var and local
shadowing.</p><p>Note: Special forms are not necessarily qualified. See section 'Special Forms in Detail'.</p><h3 id="generated-symbols-gensyms">Generated Symbols (gensyms)</h3><p>Automatic namespace generation is fine in some cases, but not every time. Sometimes
a symbol name that is unique in the macro scope is necessary.</p><p>Unique symbols names can be generated with the <code>clojure.core/gensym</code> function that
take an optional base string:</p><pre><code class="klipse-clojure nohighlight">(gensym)
;= G__54
</code></pre><pre><code class="klipse-clojure nohighlight">(gensym "base")
;= base57
</code></pre><p>There is a shortcut: if a symbol ends in <code>#</code> within a syntax quote form, it will be
expanded by the compiler into a gensym (aka. an auto-gensym):</p><pre><code class="clojure">(defmacro yes-no-&gt;boolean
[val]
`(let [b# (= ~val "yes")]
b#))
;= #'user/yes-no-&gt;boolean
</code></pre><pre><code class="klipse-clojure nohighlight">(macroexpand-1 '(yes-no-&gt;boolean "yes"))
;= (clojure.core/let [b__148__auto__ (clojure.core/= "yes" "yes")] b__148__auto__)
</code></pre><p>The name that replaced <code>b#</code> was generated by the compiler to make unwanted variable
capture very unlikely in practice, and impossible if all bindings are named with auto-gensym.</p><p>Theoretically, Clojure's approach to generating uncaptured gensyms (incrementing a global counter) can be circumvented
via a mischievous macro or very bad luck.</p><p>Tip:
Avoid code with <code>__</code> in local binding names. This ensures
auto-gensyms are <em>never</em> captured in unwanted ways.</p><h2 id="macroexpansions">Macroexpansions</h2><p>During macro development, it is important to be able to test the macro
and see what data structures the macro expands to. This can be done
with two functions in the core Clojure library:</p><ul><li><code>clojure.core/macroexpand-1</code></li><li><code>clojure.core/macroexpand</code></li><li><code>clojure.walk/macroexpand-all</code></li></ul><p>The difference between the two is that <code>macroexpand-1</code> will expand the macro
only once. If the result contains calls to other macros, those won't be expanded.
<code>macroexpand</code>, however, will continue expanding all macros until the top level form
is no longer a macro.</p><p>Both macroexpansion functions take quoted forms.</p><p>Macro expansion functions can be used to find out that <code>when</code> is a macro implemented on top of
the <code>if</code> special form, for example:</p><pre><code class="klipse-clojure nohighlight">(macroexpand '(when true 1 42))
</code></pre><h3 id="full-macroexpansion">Full Macroexpansion</h3><p>Neither <code>macroexpand-1</code> nor <code>macroexpand</code> expand nested
forms. To fully expand macros including those in nested forms, there is <code>clojure.walk/macroexpand-all</code>,
which, however, is not part of Clojure core and does not behave exactly the same way
the compiler does.</p><h2 id="difference-between-quote-and-syntax-quote">Difference Between Quote and Syntax Quote</h2><p>The key difference between quote and syntax quote is that
symbols within a syntax quoted form are automatically namespace-qualified.</p><h2 id="security-considerations">Security Considerations</h2><p><code>clojure.core/read-string</code> <em>can execute arbitrary code</em> and <em>must not</em> be used
on inputs coming from untrusted sources. This behavior is controlled by the <code>clojure.core/*read-eval*</code>
var. Starting with Clojure 1.5, the default value of <code>*read-eval*</code> is <code>false</code>.</p><p><code>*read-eval*</code> can be disabled via a property when starting the JVM:</p><pre><code>-Dclojure.read.eval=false
</code></pre><p>When reading Clojure forms from untrusted sources, use <code>clojure.edn/read-string</code>, which is
does not perform arbitrary code execution and is safer. <code>clojure.edn/read-string</code> implements
the <a href="https://github.com/edn-format/edn">EDN format</a>, a subset of Clojure syntax for data
structures. <code>clojure.edn</code> was introduced in Clojure 1.5.</p><h2 id="special-forms-in-detail">Special Forms in Detail</h2><p>Special forms are restrictive in their use and do not interact cleanly with several area of Clojure.</p><ul><li><p>Special forms must be a list with a special name as the first element.</p><p>A special name in a higher-order context is not a special form.</p><pre><code class="klipse-clojure nohighlight">do
;; CompilerException java.lang.RuntimeException: Unable to resolve symbol: do in this context, compiling:(NO_SOURCE_PATH:0:0)
</code></pre><p>Macros have a similar restriction, but notice: the macro's var is identified in the error while
special names have no meaning at all outside the first element of a list.</p><pre><code class="klipse-clojure nohighlight">dosync
;; CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/dosync, compiling:(NO_SOURCE_PATH:0:0)
</code></pre></li><li><p>Special form names are not namespace-qualified.</p><p>Most special forms (all except <code>clojure.core/import*</code>) are not namespace
qualified. The reader must circumvent syntax quote's policy of namespace-qualifying
all symbols.</p><pre><code class="klipse-clojure nohighlight">`a
;; user/a
</code></pre><pre><code class="klipse-clojure nohighlight">`do
;; do
</code></pre><pre><code class="clojure">user=&gt; `if
if
user=&gt; `import*
user/import*
</code></pre></li><li><p>Special forms conflict with local scope.</p><p>Never use special names as local binding or global variable names.</p><pre><code class="clojure">(let [do 1] do)
;;; nil
</code></pre><p>Ouch!</p><p>This includes destructuring:</p><pre><code class="clojure">user=&gt; (let [{:keys [do]} {:do 1}] do)
nil
</code></pre><p>Note: Be wary of maps with keyword keys with special names, they are more
likely to be destructured this way.</p></li></ul><p>Keep these special cases in mind as you work through the tutorial.</p><h2 id="contributors">Contributors</h2><ul><li>Michael Klishin <a href="mailto:michael@defprotocol.org">michael@defprotocol.org</a>, 2013 (original author)</li><li>Ambrose Bonnaire-Sergeant <a href="mailto:abonnairesergeant@gmail.com">abonnairesergeant@gmail.com</a>, 2013</li></ul>
<div id="prev-next">
<a href="../interop/index.html">&laquo; Clojure interoperability with Java</a>
||
<a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../functions/index.html">Functions in Clojure</a></li>
<li><a href="../laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
<link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">
<script>
window.klipse_settings = {
"selector" : ".klipse-clojure"
};
</script>
<script src="https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"></script>
</body>
</html>

View file

@ -0,0 +1,375 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Clojure Namespaces and Vars</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/namespaces/" />
<meta property="og:title" content="Clojure Namespaces and Vars" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/namespaces/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Clojure Namespaces and Vars</h2>
</div>
<p>This guide covers:</p><ul><li>An overview of Clojure namespaces and vars</li><li>How to define namespaces</li><li>How to use functions in other namespaces</li><li><code>require</code>, <code>refer</code> and <code>use</code></li><li>Common compilation errors and typical problems that cause them</li><li>Namespaces and their relation to code compilation in Clojure</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5.</p><h2 id="overview">Overview</h2><p>Clojure functions are organized into <em>namespaces</em>. Clojure namespaces
are very similar to Java packages and Python modules. Namespaces are
basically maps (dictionaries) that map names to <em>vars</em>. In many cases,
those vars store functions in them.</p><h2 id="defining-a-namespace">Defining a Namespace</h2><p>Namespaces are usually defined using the <code>clojure.core/ns</code> macro. In its basic
form, it takes a name as a symbol:</p><pre><code class="clojure">(ns superlib.core)
</code></pre><p>Namespaces can have multiple segments, separated by a dot:</p><pre><code class="clojure">(ns megacorp.service.core)
</code></pre><p>It is <strong>highly recommended</strong> to avoid using single segment namespaces
(e.g. <code>superlib</code>) to avoid inconvenient conflicts other developers
will have to work around. If a library or application belongs to an
organization or a group of projects, the
<code>[organization].[library|app].[group-of-functions]</code> pattern is
recommended. For example:</p><pre><code class="clojure">(ns clojurewerkz.welle.kv)
(ns megacorp.search.indexer.core)
</code></pre><p>In addition, the <code>ns</code> macro takes a number of optional forms:</p><ul><li><code>(:require ...)</code></li><li><code>(:import ...)</code></li><li><code>(:use ...)</code></li><li><code>(:refer-clojure ...)</code></li><li><code>(:gen-class ...)</code></li></ul><p>These are just slightly more concise variants of <code>clojure.core/import</code>, <code>clojure.core/require</code>, et cetera.</p><h3 id="the-require-helper-form">The :require Helper Form</h3><p>The <code>:require</code> helper form is for setting up access to other Clojure
namespaces from your code. For example:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:require clojure.set))
;; Now it is possible to do:
;; (clojure.set/difference #{1 2 3} #{3 4 5})
</code></pre><p>This will make sure the <code>clojure.set</code> namespace is loaded, compiled, and available as <code>clojure.set</code>
(using its fully qualified name). It is possible (and common) to make a namespace available
under an alias:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:require [clojure.set :as cs]))
;; Now it is possible to do:
;; (cs/difference #{1 2 3} #{3 4 5})
</code></pre><p>One more example with two required namespaces:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:require [clojure.set :as cs]
[clojure.walk :as walk]))
</code></pre><h4 id="the-refer-option">The :refer Option</h4><p>To make functions in <code>clojure.set</code> available in the defined namespace via short names
(i.e., their unqualified names, without the <code>clojure.set</code> or other prefix), you can tell Clojure compiler
to <em>refer</em> to certain functions:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:require [clojure.set :refer [difference intersection]]))
;; Now it is possible to do:
;; (difference #{1 2 3} #{3 4 5})
</code></pre><p>The <code>:refer</code> feature of the <code>:require</code> form is new in Clojure 1.4.</p><p>It is possible to refer to all functions in a namespace (usually not necessary):</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:require [clojure.set :refer :all]))
;; Now it is possible to do:
;; (difference #{1 2 3} #{3 4 5})
</code></pre><h3 id="the-import-helper-form">The :import Helper Form</h3><p>The <code>:import</code> helper form is for setting up access to Java classes
from your Clojure code. For example:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:import java.util.concurrent.Executors))
</code></pre><p>This will make sure the <code>java.util.concurrent.Executors</code> class is imported and can be used by its short
name, <code>Executors</code>. It is possible to import multiple classes:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:import java.util.concurrent.Executors
java.util.concurrent.TimeUnit
java.util.Date))
</code></pre><p>If multiple imported classes are in the same namespace (like in the example above),
it is possible to avoid some duplication by using an <em>import list</em>. The first element
of an import list is the package and other elements are class names in that package:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:import [java.util.concurrent Executors TimeUnit]
java.util.Date))
</code></pre><p>Even though <em>import list</em> is called a list, it can be any Clojure collection (typically
vectors are used).</p><h3 id="the-current-namespace">The Current Namespace</h3><p>Under the hood, Clojure keeps <strong>current namespace</strong> a special var, <a href="http://clojuredocs.org/clojure_core/clojure.core/*ns*">*ns*</a>.
When vars are defined using the <a href="http://clojuredocs.org/clojure_core/clojure.core/def">def</a> special form, they are
added to the current namespace.</p><h3 id="the-refer-clojure-helper-form">The :refer-clojure Helper Form</h3><p>Functions like <code>clojure.core/get</code> and macros like <code>clojure.core/defn</code> can be used without
namespace qualification because they reside in the <code>clojure.core</code> namespace and Clojure
compiler automatically <em>refers</em> all vars in it. Therefore, if your
namespace defines a function with the same name (e.g. <code>find</code>), you will get a warning
from the compiler, like this:</p><pre><code>WARNING: find already refers to: #'clojure.core/find in namespace: megacorp.profitd.scheduling, being replaced by: #'megacorp.profitd.scheduling/find
</code></pre><p>This means that in the <code>megacorp.profitd.scheduling</code> namespace, <code>find</code> already refers to
a value which happens to be <code>clojure.core/find</code>, but it is being replaced by a
different value. Remember, Clojure is a very dynamic language and namespaces are
basically maps, as far as the implementation goes. Most of the time, however,
replacing vars like this is not intentional and Clojure compiler emits a warning.</p><p>To solve this problem, you can either rename your function, or else
exclude certain <code>clojure.core</code> functions from being
referred using the <code>(:refer-clojure ...)</code> form within the <code>ns</code>:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:refer-clojure :exclude [find]))
(defn find
"Finds a needle in the haystack."
[^String haystack]
(comment ...))
</code></pre><p>In this case, to use <code>clojure.core/find</code>, you will have to use its fully
qualified name: <code>clojure.core/find</code>:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling
(:refer-clojure :exclude [find]))
(defn find
"Finds a needle in the haystack."
[^String haystack]
(clojure.core/find haystack :needle))
</code></pre><h3 id="the-use-helper-form">The :use Helper Form</h3><p>In Clojure versions before 1.4, there was no <code>:refer</code> support for the
<code>(:require ...)</code> form. Instead, a separate form was used: <code>(:use ...)</code>:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling-test
(:use clojure.test))
</code></pre><p>In the example above, <strong>all</strong> functions in <code>clojure.test</code> are made available
in the current namespace. This practice (known as "naked use") works for <code>clojure.test</code> in
test namespaces, but in general not a good idea. <code>(:use ...)</code> supports limiting
functions that will be referred:</p><pre><code class="clojure">(ns megacorp.profitd.scheduling-test
(:use clojure.test :only [deftest testing is]))
</code></pre><p>which is a pre-1.4 alternative of</p><pre><code class="clojure">(ns megacorp.profitd.scheduling-test
(:require clojure.test :refer [deftest testing is]))
</code></pre><p>It is highly recommended to use <code>(:require ...)</code> (optionally with <code>... :refer [...]</code>) on Clojure 1.4
and later releases. <code>(:use ...)</code> is a thing of the past and now that
<code>(:require ...)</code> with <code>:refer</code> is capable of doing the same thing when you
need it, it is a good idea to let <code>(:use ...)</code> go.</p><h3 id="the-gen-class-helper-form">The :gen-class Helper Form</h3><p><em>TBD: <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></em></p><h3 id="documentation-and-metadata">Documentation and Metadata</h3><p>Namespaces can have documentation strings. You can add one with the optional
<code>ns</code> macro parameter:</p><pre><code class="clojure">(ns superlib.core
"Core functionality of Superlib.
Other parts of Superlib depend on functions and macros in this namespace."
(:require [clojure.set :refer [union difference]]))
</code></pre><p>or metadata:</p><pre><code class="clojure">(ns ^{:doc "Core functionality of Superlib.
Other parts of Superlib depend on functions and macros in this namespace."
:author "Joe Smith"}
superlib.core
(:require [clojure.set :refer [union difference]]))
</code></pre><p>Metadata can contain any additional keys such as <code>:author</code> which may be of use to various tools
(such as <a href="https://clojars.org/codox">Codox</a>, <a href="https://clojars.org/cadastre">Cadastre</a>, or <a href="https://clojars.org/lein-clojuredocs">lein-clojuredocs</a>).</p><h2 id="how-to-use-functions-from-other-namespaces-in-the-repl">How to Use Functions From Other Namespaces in the REPL</h2><p>The <code>ns</code> macro is how you usually require functions from other namespaces.
However, it is not very convenient in the REPL. For that case, the <code>clojure.core/require</code> function
can be used directly:</p><pre><code class="clojure">;; Will be available as clojure.set, e.g. clojure.set/difference.
(require 'clojure.set)
;; Will be available as io, e.g. io/resource.
(require '[clojure.java.io :as io])
</code></pre><p>It takes a quoted <em><a href="https://clojure-doc.org/articles/language/namespaces/glossary.html#libspec">libspec</a></em>. The libspec is either a namespace name or
a collection (typically a vector) of <code>[name :as alias]</code> or <code>[name :refer [fns]]</code>:</p><pre><code class="clojure">(require '[clojure.set :refer [difference]])
(difference #{1 2 3} #{3 4 5 6}) ; ⇒ #{1 2}
</code></pre><p>The <code>:as</code> and <code>:refer</code> options can be used together:</p><pre><code class="clojure">(require '[clojure.set :as cs :refer [difference]])
(difference #{1 2 3} #{3 4 5 6}) ; ⇒ #{1 2}
(cs/union #{1 2 3} #{3 4 5 6}) ; ⇒ #{1 2 3 4 5 6}
</code></pre><p><code>clojure.core/use</code> does the same thing as <code>clojure.core/require</code> but with the
<code>:refer</code> option (as discussed above). It is not generally recommended to use <code>use</code> with Clojure
versions starting with 1.4. Use <code>clojure.core/require</code> with <code>:refer</code>
instead.</p><h2 id="namespaces-and-class-generation">Namespaces and Class Generation</h2><p><em>TBD: <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></em></p><h2 id="namespaces-and-code-compilation-in-clojure">Namespaces and Code Compilation in Clojure</h2><p>Clojure is a compiled language: code is compiled when it is loaded (usually with <code>clojure.core/require</code>).</p><p>A namespace can contain vars or be used purely to extend protocols, add multimethod implementations,
or conditionally load other libraries (e.g. the most suitable JSON parser or key/value store implementation).
In all cases, to trigger compilation, you need to require the namespace.</p><h2 id="private-vars">Private Vars</h2><p>Vars (and, in turn, functions defined with <code>defn</code>) can be private. There are two equivalent ways to
specify that a function is private: either via metadata or by using the <code>defn-</code> macro:</p><pre><code class="clojure">(ns megacorp.superlib)
;;
;; Implementation
;;
(def ^{:private true}
source-name "supersource")
(defn- data-stream
[source]
(comment ...))
</code></pre><h2 id="constant-vars">Constant Vars</h2><p>Vars can be constant. This is done by setting the <code>:const</code> metadata key to <code>true</code>. This
will cause Clojure compiler to compile it as a constant:</p><pre><code class="clojure">(ns megacorp.epicgame)
;;
;; Implementation
;;
(def ^{:const true}
default-score 100)
</code></pre><h2 id="how-to-look-up-and-invoke-a-function-by-name">How to Look up and Invoke a Function by Name</h2><p>It is possible to look up a function in particular namespace by-name with <code>clojure.core/ns-resolve</code>. This takes
quoted names of the namespace and function. The returned value can be used just like any other
function, for example, passed as an argument to a higher order function:</p><pre><code class="clojure">(ns-resolve 'clojure.set 'difference) ; ⇒ #'clojure.set/difference
(let [f (ns-resolve 'clojure.set 'difference)]
(f #{1 2 3} #{3 4 5 6})) ; ⇒ #{1 2}
</code></pre><h2 id="compiler-exceptions">Compiler Exceptions</h2><p>This section describes some common compilation errors.</p><h3 id="classnotfoundexception">ClassNotFoundException</h3><p>This exception means that JVM could not load a class. It is either misspelled or not on the
<a href="https://clojure-doc.org/articles/language/namespaces/glossary.html#classpath">classpath</a>.
Potentially your project has unsatisfied dependency (some dependencies may be optional).</p><p>Example:</p><pre><code class="clojure">user=&gt; (import java.uyil.concurrent.TimeUnit)
ClassNotFoundException java.uyil.concurrent.TimeUnit java.net.URLClassLoader$1.run (URLClassLoader.java:366)
</code></pre><p>In the example above, <code>java.uyil.concurrent.TimeUnit</code> should have been <code>java.util.concurrent.TimeUnit</code>.</p><h3 id="compilerexception-javalangruntimeexception-no-such-var">CompilerException java.lang.RuntimeException: No such var</h3><p>This means that somewhere in the code a non-existent var is used. It may be a typo, an
incorrect macro-generated var name or a similar issue. Example:</p><pre><code class="clojure">user=&gt; (clojure.java.io/resouce "thought_leaders_quotes.csv")
CompilerException java.lang.RuntimeException: No such var: clojure.java.io/resouce, compiling:(NO_SOURCE_PATH:1)
</code></pre><p>In the example above, <code>clojure.java.io/resouce</code> should have been <code>clojure.java.io/resource</code>. <code>NO_SOURCE_PATH</code>
means that compilation was triggered from the REPL and not a Clojure source file.</p><h2 id="temporarily-overriding-vars-in-namespaces">Temporarily Overriding Vars in Namespaces</h2><p><em>TBD: <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></em></p><h2 id="getting-information-about-and-programmatically-manipulating-namespaces">Getting Information About and Programmatically Manipulating Namespaces</h2><p><em>TBD: <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></em></p><h2 id="wrapping-up">Wrapping Up</h2><p>Namespaces are basically maps (dictionaries) that map names to
vars. In many cases, those vars store functions in them.</p><p>This implementation lets Clojure have many of its highly dynamic
features at a very reasonable runtime overhead cost. For example, vars
in namespaces can be temporarily altered for unit testing purposes.</p><h2 id="contributors">Contributors</h2><p>Michael Klishin <a href="mailto:michael@defprotocol.org">michael@defprotocol.org</a> (original author)</p>
<div id="prev-next">
<a href="../core_overview/index.html">&laquo; Overview of clojure.core, the standard Clojure library</a>
||
<a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../functions/index.html">Functions in Clojure</a></li>
<li><a href="../laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,385 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Polymorphism in Clojure: Protocols and Multimethods</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/language/polymorphism/" />
<meta property="og:title" content="Polymorphism in Clojure: Protocols and Multimethods" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/language/polymorphism/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Polymorphism in Clojure: Protocols and Multimethods</h2>
</div>
<p>This guide covers:</p><ul><li>What are polymorphic functions</li><li>Type-based polymorphism with protocols</li><li>Ad-hoc polymorphism with multimethods</li><li>How to create your own data types that behave like core Clojure data types</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5.</p><h2 id="overview">Overview</h2><p>According to Wikipedia,</p><blockquote><p>In computer science, polymorphism is a programming language feature that allows values of different data types to be handled using a uniform interface.</p></blockquote><p>Polymorphism is not at all unique to object-oriented programming languages. Clojure has excellent support for
polymorphism.</p><p>For example, when a function can be used on multiple data types or behave differently based on additional argument
(often called <em>dispatch value</em>), that function is <em>polymorphic</em>. A simple example of such function is a function that
serializes its input to JSON (or other format).</p><p>Ideally, developers would like to use the same function regardless of the input, and be able to extend
it to new inputs, without having to change the original source. Inability to do so is known as the <a href="http://en.wikipedia.org/wiki/Expression_problem">Expression Problem</a>.</p><p>In Clojure, there are two approaches to polymorphism:</p><ul><li>Data type-oriented. More efficient (modern JVMs optimize this case very well), less flexible.</li><li>So called "ad-hoc polymorphism" where the exact function implementation is picked at runtime based on a special argument (<em>dispatch value</em>).</li></ul><p>The former is implemented using <em>protocols</em>, a feature first introduced in Clojure 1.2. The latter is available via
<em>multimethods</em>, a feature that was around in Clojure since the early days.</p><h2 id="type-based-polymorphism-with-protocols">Type-based Polymorphism With Protocols</h2><p>It is common for polymorphic functions to <em>dispatch</em> (pick implementation) on the type of the first argument. For example,
in Java or Ruby, when calling <code>#toString</code> or <code>#to_s</code> on an object, the exact implementation is located using that object's
type.</p><p>Because this is a common case and because JVM can optimize this dispatch logic very well, Clojure 1.2 introduced a new
feature called <em>protocols</em>. Protocols are simply groups of functions. Each of the functions can have different
implementations for different data types.</p><p>Protocols are defined using the <code>clojure.core/defprotocol</code> special form. The example below defines a protocol for working with URLs and URIs.
While URLs and URIs are not the same thing, some operations make sense for both:</p><pre><code class="clojure">(defprotocol URLLike
"Unifies operations on URLs and URIs"
(^String protocol-of [input] "Returns protocol of given input")
(^String host-of [input] "Returns host of given input")
(^String port-of [input] "Returns port of given input")
(^String user-info-of [input] "Returns user information of given input")
(^String path-of [input] "Returns path of given input")
(^String query-of [input] "Returns query string of given input")
(^String fragment-of [input] "Returns fragment of given input"))
</code></pre><p><code>clojure.core/defprotocol</code> takes the name of the protocol and one or more lists of
<strong>function name</strong>, <strong>argument list</strong>, <strong>documentation string</strong>:</p><pre><code class="clojure">(^String protocol-of [input] "Returns protocol of given input")
(^String host-of [input] "Returns host of given input")
</code></pre><p>The example above uses return type hints. This makes sense in the example but is not necessary. It could have been written
it as</p><pre><code class="clojure">(defprotocol URLLike
"Unifies operations on URLs and URIs"
(protocol-of [input] "Returns protocol of given input")
(host-of [input] "Returns hostname of given input")
(port-of [input] "Returns port of given input")
(user-info-of [input] "Returns user information (username:password) of given input")
(path-of [input] "Returns path of given input")
(query-of [input] "Returns query string of given input")
(fragment-of [input] "Returns fragment of given input"))
</code></pre><p>There are 3 ways URIs and URLs are commonly represented on the JVM:</p><ul><li><code>java.net.URI</code> instances</li><li><code>java.net.URL</code> instances</li><li>Strings</li></ul><p>When a new protocol imlementation is added for a type, it is called <strong>extending the protocol</strong>. The most common way to extend
a protocol is via the <code>clojure.core/extend-protocol</code>:</p><pre><code class="clojure">(import java.net.URI)
(import java.net.URL)
(extend-protocol URLLike
URI
(protocol-of [^URI input]
(when-let [s (.getScheme input)]
(.toLowerCase s)))
(host-of [^URI input]
(-&gt; input .getHost .toLowerCase))
(port-of [^URI input]
(.getPort input))
(user-info-of [^URI input]
(.getUserInfo input))
(path-of [^URI input]
(.getPath input))
(query-of [^URI input]
(.getQuery input))
(fragment-of [^URI input]
(.getFragment input))
URL
(protocol-of [^URL input]
(protocol-of (.toURI input)))
(host-of [^URL input]
(host-of (.toURI input)))
(port-of [^URL input]
(.getPort input))
(user-info-of [^URL input]
(.getUserInfo input))
(path-of [^URL input]
(.getPath input))
(query-of [^URL input]
(.getQuery input))
(fragment-of [^URL input]
(.getRef input)))
</code></pre><p>Protocol functions are used just like regular Clojure functions:</p><pre><code class="clojure">(protocol-of (URI. "https://clojure-doc.github.io")) ;= "http"
(protocol-of (URL. "https://clojure-doc.github.io")) ;= "http"
(path-of (URL. "https://clojure-doc.github.io/articles/content.html")) ;= "/articles/content/"
(path-of (URI. "https://clojure-doc.github.io/articles/content.html")) ;= "/articles/content/"
</code></pre><h3 id="using-protocols-from-different-namespaces">Using Protocols From Different Namespaces</h3><p>Protocol functions are required and used the same way as regular protocol functions. Consider a
namespace that looks like this</p><pre><code class="clojure">(ns superlib.url-like
(:import [java.net URL URI]))
(defprotocol URLLike
"Unifies operations on URLs and URIs"
(^String protocol-of [input] "Returns protocol of given input")
(^String host-of [input] "Returns host of given input")
(^String port-of [input] "Returns port of given input")
(^String user-info-of [input] "Returns user information of given input")
(^String path-of [input] "Returns path of given input")
(^String query-of [input] "Returns query string of given input")
(^String fragment-of [input] "Returns fragment of given input"))
(extend-protocol URLLike
URI
(protocol-of [^URI input]
(when-let [s (.getScheme input)]
(.toLowerCase s)))
(host-of [^URI input]
(-&gt; input .getHost .toLowerCase))
(port-of [^URI input]
(.getPort input))
(user-info-of [^URI input]
(.getUserInfo input))
(path-of [^URI input]
(.getPath input))
(query-of [^URI input]
(.getQuery input))
(fragment-of [^URI input]
(.getFragment input))
URL
(protocol-of [^URL input]
(protocol-of (.toURI input)))
(host-of [^URL input]
(host-of (.toURI input)))
(port-of [^URL input]
(.getPort input))
(user-info-of [^URL input]
(.getUserInfo input))
(path-of [^URL input]
(.getPath input))
(query-of [^URL input]
(.getQuery input))
(fragment-of [^URL input]
(.getRef input)))
</code></pre><p>To use <code>superlib.url-like/path-of</code> and other functions, you require them as regular functions:</p><pre><code class="clojure">(ns myapp
(:require [superlib.url-like] :refer [host-of scheme-of]))
(host-of (java.net.URI. "https://twitter.com/cnn/"))
</code></pre><h3 id="extending-protocols-for-core-clojure-data-types">Extending Protocols For Core Clojure Data Types</h3><p>TBD</p><h3 id="protocols-and-custom-data-types">Protocols and Custom Data Types</h3><p>TBD: cover extend-type, extend</p><h3 id="partial-implementation-of-protocols">Partial Implementation of Protocols</h3><p>With protocols, it is possible to only implement certain functions for certain types.</p><h2 id="ad-hoc-polymorphism-with-multimethods">Ad-hoc Polymorphism with Multimethods</h2><h3 id="first-example-shapes">First Example: Shapes</h3><p>Lets start with a simple problem definition. We have 3 shapes: square, circle and triangle, and
need to provide an polymorphic function that calculates the area of the given shape.</p><p>In total, we need 4 functions:</p><ul><li>A function that calculates area of a square</li><li>A function that calculates area of a circle</li><li>A function that calculates area of a triangle</li><li>A polymorphic function that acts as a "unified frontend" to the functions above</li></ul><p>we will start with the latter and define a <em>multimethod</em> (not related to methods on Java objects or object-oriented programming):</p><pre><code class="klipse-clojure nohighlight">(defmulti area (fn [shape &amp; _]
shape))
</code></pre><p>Our multimethod has a name and a <em>dispatch function</em> that takes arguments passed to the multimethod and returns
a value. The returned value will define what implementation of multimethod is used. In Java or Ruby, method implementation
is picked by traversing the class hierarchy. With multimethods, the logic can be anything you need. That's why it is
called <em>ad-hoc polymorphism</em>.</p><p>An alternative way of doing the same thing is to pass <code>clojure.core/first</code> instead of an anonymous function:</p><pre><code class="klipse-clojure nohighlight">(defmulti area first)
</code></pre><p>Next lets implement our area multimethod for squares:</p><pre><code class="klipse-clojure nohighlight">(defmethod area :square
[_ side]
(* side side))
</code></pre><p>Here <code>defmethod</code> defines a particular implementation of the multimethod <code>area</code>, the one that will be used if dispatch function
returns <code>:square</code>. Lets try it out. Multimethods are invoked like regular Clojure functions:</p><pre><code class="klipse-clojure nohighlight">(area :square 4)
;= 16
</code></pre><p>In this case, we pass dispatch value as the first argument, our dispatch function returns it unmodified and
that's how the exact implementation is looked up.</p><p>Implementation for circles looks very similar, we choose <code>:circle</code> as a reasonable dispatch value:</p><pre><code class="klipse-clojure nohighlight">(defmethod area :circle
[_ radius]
(* radius radius Math/PI))
(area :circle 3)
;= 28.274333882308138
</code></pre><p>For the record, <code>Math/PI</code> in this example refers to <code>java.lang.Math/PI</code>, a field that stores the value of Pi.</p><p>Finally, an implementation for triangles. Here you can see that exact implementations can take different number of
arguments. To calculate the area of a triangle, we multiple base by height and divide it by 2:</p><pre><code class="klipse-clojure nohighlight">(defmethod area :triangle
[_ b h]
(* 1/2 b h))
(area :triangle 3 5)
;= 15/2
</code></pre><p>In this example we used <strong>Clojure ratio</strong> data type. We could have used doubles as well.</p><p>Putting it all together:</p><pre><code class="klipse-clojure nohighlight">(defmulti area (fn [shape &amp; _]
shape))
(defmethod area :square
[_ side]
(* side side))
(defmethod area :circle
[_ radius]
(* radius radius Math/PI))
(defmethod area :triangle
[_ b h]
(* 1/2 b h))
</code></pre><pre><code class="klipse-clojure nohighlight">(area :square 4)
;= 16
</code></pre><pre><code class="klipse-clojure nohighlight">(area :circle 3)
;= 28.274333882308138
</code></pre><pre><code class="klipse-clojure nohighlight">(area :triangle 3 5)
;= 15/2
</code></pre><h3 id="second-example-tbd">Second Example: TBD</h3><p>TBD: an example that demonstrates deriving</p><h2 id="how-to-create-custom-data-type-that-core-functions-can-work-with">How To Create Custom Data Type That Core Functions Can Work With</h2><p>TBD: <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></p><h2 id="wrapping-up">Wrapping Up</h2><p>TBD: <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></p>
<div id="prev-next">
<a href="../macros/index.html">&laquo; Clojure Macros and Metaprogramming</a>
||
<a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../functions/index.html">Functions in Clojure</a></li>
<li><a href="../laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
<link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">
<script>
window.klipse_settings = {
"selector" : ".klipse-clojure"
};
</script>
<script src="https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"></script>
</body>
</html>

View file

@ -0,0 +1,476 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Basic Web Development</title>
<meta name="description" content="This guide covers building a simple web-application using common
Clojure libraries. When you&#39;re done working through it, you&#39;ll have a
little webapp that displays some (x, y) locations from a database,
letting you add more locations as well.It&#39;s assumed that you&#39;re already somewhat familiar with Clojure. If
not, see the Getting Started and
Introduction guides.">
<meta property="og:description" content="This guide covers building a simple web-application using common
Clojure libraries. When you&#39;re done working through it, you&#39;ll have a
little webapp that displays some (x, y) locations from a database,
letting you add more locations as well.It&#39;s assumed that you&#39;re already somewhat familiar with Clojure. If
not, see the Getting Started and
Introduction guides.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/tutorials/basic_web_development/" />
<meta property="og:title" content="Basic Web Development" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/tutorials/basic_web_development/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Basic Web Development</h2>
</div>
<p>This guide covers building a simple web-application using common
Clojure libraries. When you're done working through it, you'll have a
little webapp that displays some (x, y) locations from a database,
letting you add more locations as well.</p><p>It's assumed that you're already somewhat familiar with Clojure. If
not, see the <a href="https://clojure-doc.org/articles/tutorials/basic_web_development/getting_started/">Getting Started</a> and
<a href="https://clojure-doc.org/articles/tutorials/basic_web_development/introduction/">Introduction</a> guides.</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><p>This guide uses Clojure 1.5, as well as current versions of the
component libraries noted below.</p><h2 id="conceptual-overview-of-components">Conceptual Overview of Components</h2><p>We'll use four major components (briefly described below) for our
little webapp:</p><ul><li>Ring</li><li>Compojure</li><li>Hiccup</li><li>H2</li></ul><h3 id="ring">Ring</h3><p><a href="https://github.com/ring-clojure/ring">Ring</a> (<a href="https://clojars.org/ring">at
clojars</a>) is a foundational Clojure web
application library. It:</p><ul><li>sets things up such that an http request comes into your webapp
as a regular Clojure hashmap, and likewise makes it so that you
can return a response as a hashmap.</li><li>provides <a href="https://github.com/ring-clojure/ring/blob/master/SPEC">a
spec</a>
describing exactly what those request and response maps should
look like.</li><li>brings along a web server
(<a href="http://www.eclipse.org/jetty/">Jetty</a>) and connects your
webapp to it.</li></ul><p>For this tutorial, we won't actually need to deal with these maps
by-hand, as you'll soon see.</p><p>For more info, see:</p><ul><li><a href="https://github.com/ring-clojure/ring#readme">the Ring readme</a></li><li><a href="https://github.com/ring-clojure/ring/wiki">its wiki docs</a></li><li><a href="http://ring-clojure.github.com/ring/">its API docs</a></li></ul><h3 id="compojure">Compojure</h3><p>If we were using only Ring, we'd have to write one single function to
take that incoming request map and then delegate to various functions
depending upon which page was requested.
<a href="https://github.com/weavejester/compojure">Compojure</a> (<a href="https://clojars.org/compojure">at
clojars</a>) provides some handy features
to take care of this for us such that we can associate url paths with
corresponding functions, all in one place.</p><p>For more info, see:</p><ul><li><a href="https://github.com/weavejester/compojure#readme">the Compojure readme</a></li><li><a href="https://github.com/weavejester/compojure/wiki">its wiki docs</a></li><li><a href="http://weavejester.github.com/compojure/">its API docs</a></li></ul><h3 id="hiccup">Hiccup</h3><p><a href="https://github.com/weavejester/hiccup">Hiccup</a> (<a href="https://clojars.org/hiccup">at
clojars</a>) provides a quick and easy way to
generate html. It converts regular Clojure data structures right into
html. For example,</p><pre><code class="clojure">[:p "Hello, " [:i "doctor"] " Jones."]
</code></pre><p>becomes</p><pre><code class="html">&lt;p&gt;Hello, &lt;i&gt;doctor&lt;/i&gt; Jones.&lt;/p&gt;
</code></pre><p>but it also does two extra handy bits of magic:</p><ul><li><p>it provides some CSS-like shortcuts for specifying id and class,
and</p></li><li><p>it automatically unpacks seqs for you, for example:</p><pre><code class="clojure">[:p '("a" "b" "c")]
;; expands to (and so, is the same as if you wrote)
[:p "a" "b" "c"]
</code></pre></li></ul><p>For more info, see:</p><ul><li><a href="https://github.com/weavejester/hiccup#readme">the Hiccup readme</a></li><li><a href="https://github.com/weavejester/hiccup/wiki">its wiki docs</a></li><li><a href="http://weavejester.github.com/hiccup/">its API docs</a></li></ul><h3 id="h2">H2</h3><p><a href="http://www.h2database.com/html/main.html">H2</a> is a small and fast Java SQL
database that could be embedded in your application or run in server
mode. Uses single file for storage, but also could be run as in-memory DB.</p><blockquote><p>Another similar Java-based embedded DB that could be used in your
application is <a href="http://db.apache.org/derby/">Apache Derby</a>.</p></blockquote><h2 id="create-and-set-up-your-project">Create and set up your project</h2><p>Create your new webapp project like so:</p><pre><code class="bash">lein new compojure my-webapp
cd my-webapp
</code></pre><p>Add the following extra dependencies to your project.clj's
<code>:dependencies</code> vector:</p><pre><code class="clojure">[hiccup "1.0.5"]
[org.clojure/java.jdbc "0.6.0"]
[com.h2database/h2 "1.4.193"]
</code></pre><p>(You might also remove the <code>-SNAPSHOT</code> from the project's version
string.)</p><h2 id="add-some-styling">Add some styling</h2><pre><code class="bash">mkdir -p resources/public/css
touch resources/public/css/styles.css
</code></pre><p>and put into that file something like:</p><pre><code class="css">body {
background-color: Cornsilk;
}
#header-links {
background-color: BurlyWood;
padding: 10px;
}
h1 {
color: CornflowerBlue;
}
</code></pre><h2 id="set-up-your-database">Set up your database</h2><p>A file with DB would be automatically created when you connect to it for the
first time, so all necessary DB preparations could be done programmatically
using the REPL (with help of <code>clojure.java.jdbc</code>):</p><pre><code class="bash">lein repl
</code></pre><p>Execute the following code to create a new my-webapp.h2.db database file in db
subdirectory of your project, create a table we'll use for our webapp, and add
one record to start us off with:</p><pre><code class="clojure">(require '[clojure.java.jdbc :as jdbc])
(jdbc/with-db-connection [conn {:dbtype "h2" :dbname "./my-webapp"}]
(jdbc/db-do-commands conn
(jdbc/create-table-ddl :locations
[[:id "bigint primary key auto_increment"]
[:x "integer"]
[:y "integer"]]))
(jdbc/insert! conn :locations
{:x 8 :y 9}))
</code></pre><p>and hit <code>ctrl-d</code> to exit.</p><p>For more about how to use the database functions, see the
<a href="../../ecosystem/java_jdbc/home.html">Using java.jdbc</a> on this site.</p><h2 id="set-up-your-routes">Set up your routes</h2><p>In the default <code>src/my_webapp/handler.clj</code> file you're provided, we
specify our webapp's <em>routes</em> inside the <code>defroutes</code> macro. That is,
we assign a function to handle each of the url paths we'd like to
support, and then at the end provide a "not found" page for any other
url paths.</p><p>Make your handler.clj file look like this:</p><pre><code class="clojure">(ns my-webapp.handler
(:require [my-webapp.views :as views] ; add this require
[compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes ; replace the generated app-routes with this
(GET "/"
[]
(views/home-page))
(GET "/add-location"
[]
(views/add-location-page))
(POST "/add-location"
{params :params}
(views/add-location-results-page params))
(GET "/location/:loc-id"
[loc-id]
(views/location-page loc-id))
(GET "/all-locations"
[]
(views/all-locations-page))
(route/resources "/")
(route/not-found "Not Found"))
(def app
(wrap-defaults app-routes site-defaults))
</code></pre><p>Each of those expressions in <code>defroutes</code> like <code>(GET ...)</code> or <code>(POST ...)</code> are
so-called "routes". They each evaluate to a function that
takes a ring request hashmap and returns a response hashmap. Your
<code>views/foo</code> function's job is to return that response hashmap, but note
that Compojure is kind enough to make a suitable response map out of
any html you return.</p><p>So, all you actually need to do now is write your views functions to
return some html.</p><p>Incidentally, note the special destructuring that Compojure does for
you in each of those routes. It can pull out url query (and body)
parameters, as well as pieces of the url path requested, and hand them
to your views functions. Read more about that at <a href="https://github.com/weavejester/compojure/wiki/Destructuring-Syntax">Compojure
destructuring</a>.</p><h2 id="create-your-views">Create your Views</h2><p>Create a <code>src/my_webapp/views.clj</code> file and make it look like:</p><pre><code class="clojure">(ns my-webapp.views
(:require [my-webapp.db :as db]
[clojure.string :as str]
[hiccup.page :as page]
[ring.util.anti-forgery :as util]))
(defn gen-page-head
[title]
[:head
[:title (str "Locations: " title)]
(page/include-css "/css/styles.css")])
(def header-links
[:div#header-links
"[ "
[:a {:href "/"} "Home"]
" | "
[:a {:href "/add-location"} "Add a Location"]
" | "
[:a {:href "/all-locations"} "View All Locations"]
" ]"])
(defn home-page
[]
(page/html5
(gen-page-head "Home")
header-links
[:h1 "Home"]
[:p "Webapp to store and display some 2D (x,y) locations."]))
(defn add-location-page
[]
(page/html5
(gen-page-head "Add a Location")
header-links
[:h1 "Add a Location"]
[:form {:action "/add-location" :method "POST"}
(util/anti-forgery-field) ; prevents cross-site scripting attacks
[:p "x value: " [:input {:type "text" :name "x"}]]
[:p "y value: " [:input {:type "text" :name "y"}]]
[:p [:input {:type "submit" :value "submit location"}]]]))
(defn add-location-results-page
[{:keys [x y]}]
(let [id (db/add-location-to-db x y)]
(page/html5
(gen-page-head "Added a Location")
header-links
[:h1 "Added a Location"]
[:p "Added [" x ", " y "] (id: " id ") to the db. "
[:a {:href (str "/location/" id)} "See for yourself"]
"."])))
(defn location-page
[loc-id]
(let [{x :x y :y} (db/get-xy loc-id)]
(page/html5
(gen-page-head (str "Location " loc-id))
header-links
[:h1 "A Single Location"]
[:p "id: " loc-id]
[:p "x: " x]
[:p "y: " y])))
(defn all-locations-page
[]
(let [all-locs (db/get-all-locations)]
(page/html5
(gen-page-head "All Locations in the db")
header-links
[:h1 "All Locations"]
[:table
[:tr [:th "id"] [:th "x"] [:th "y"]]
(for [loc all-locs]
[:tr [:td (:id loc)] [:td (:x loc)] [:td (:y loc)]])])))
</code></pre><p>Here we've implemented each function used in <code>handler.clj</code>.</p><p>Again, note that each of the functions with names ending in "-page"
(the ones being called in <code>handler.clj</code>) is returning just a plain
string consisting of html markup. In handler.clj's <code>defroutes</code>,
Compojure is helpfully taking care of placing that into a response
hashmap for us.</p><p>Rather than clog up this file with database-related calls, we've put
them all into their own <code>db.clj</code> file (described next).</p><h2 id="create-some-db-access-functions">Create some db access functions</h2><p>Create a <code>src/my_webapp/db.clj</code> file and make it look like:</p><pre><code class="clojure">(ns my-webapp.db
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec {:dbtype "h2" :dbname "./my-webapp"})
(defn add-location-to-db
[x y]
(let [results (jdbc/insert! db-spec :locations {:x x :y y})]
(assert (= (count results) 1))
(first (vals (first results)))))
(defn get-xy
[loc-id]
(let [results (jdbc/query db-spec
["select x, y from locations where id = ?" loc-id])]
(assert (= (count results) 1))
(first results)))
(defn get-all-locations
[]
(jdbc/query db-spec "select id, x, y from locations"))
</code></pre><p>Note that <code>jdbc/query</code> returns a seq of maps. Each map
entry's key is a column name (as a Clojure keyword), and its value is
the value for that column.</p><p>You'll also notice that we used a plain string in <code>get-all-locations</code>,
rather than putting it in a vector. <code>java.jdbc</code> allows us to omit the vector
wrapping when we have a simple SQL query with no parameters.</p><p>Of course, you can try out all these calls yourself in the REPL,
if you like:</p><pre><code>~/temp/my-webapp$ lein repl
...
user=&gt; (require 'my-webapp.db)
nil
user=&gt; (ns my-webapp.db)
nil
my-webapp.db=&gt; (jdbc/query db-spec
#_=&gt; "select x, y from locations where id = 1")
({:y 9, :x 8})
</code></pre><h2 id="run-your-webapp-during-development">Run your webapp during development</h2><p>You can run your webapp via lein:</p><pre><code>lein ring server
</code></pre><p>It should start up and also open a browser window for you pointed at
<a href="http://localhost:3000">http://localhost:3000</a>. You should be able to stop the webapp by
hitting <code>ctrl-c</code>.</p><p>If you don't want it to automatically open a
browser window, run it like so:</p><pre><code>lein ring server-headless
</code></pre><h2 id="deploy-your-webapp">Deploy your webapp</h2><p>To make your webapp suitable for deployment, make the following
changes:</p><h3 id="changes-in-projectclj">Changes in project.clj</h3><p>In your <code>project.clj</code> file:</p><ul><li><p>add to <code>:dependencies</code> (the version should generally match <code>compojure</code>s version):</p><pre><code class="clojure">[ring/ring-jetty-adapter "1.5.1"] ; e.g., for compojure version 1.5.1
</code></pre></li><li><p>and also add <code>:main my-webapp.handler</code></p></li></ul><h3 id="changes-in-handlerclj">Changes in handler.clj</h3><p>In <code>src/my_webapp/handler.clj</code>:</p><ul><li>in your <code>ns</code> macro:
<ul><li>add <code>[ring.adapter.jetty :as jetty]</code> to the <code>:require</code>, and</li><li>add <code>(:gen-class)</code> to the end</li></ul></li></ul><p>The <code>ns</code> form should now look like this:</p><pre><code class="clojure">(ns my-webapp.handler
(:require [my-webapp.views :as views]
[compojure.core :refer :all]
[compojure.route :as route]
[ring.adapter.jetty :as jetty] ; add this require
[ring.middleware.defaults :refer [wrap-defaults site-defaults]])
(:gen-class)) ; and add this gen-class
</code></pre><ul><li><p>and at the bottom, add the following <code>-main</code> function:</p><pre><code class="clojure">(defn -main
[&amp; [port]]
(let [port (Integer. (or port
(System/getenv "PORT")
5000))]
(jetty/run-jetty #'app {:port port
:join? false})))
</code></pre></li></ul><h3 id="build-and-run-it">Build and Run it</h3><p>Now create an uberjar of your webapp:</p><pre><code>lein uberjar
</code></pre><p>And now you can run it directly:</p><pre><code>java -jar target/my-webapp-0.1.0-standalone.jar 8080
</code></pre><p>(or on whatever port number you wish). If you run the JAR file from another
folder, remember to copy the <code>my-webapp.mv.db</code> file to that folder!</p><p><em>NOTE: if you did not remove "-SNAPSHOT" from the project's version string
when you first edited <code>project.clj</code>, then the JAR file will have <code>-SNAPSHOT</code>
in its name.</em></p><h2 id="see-also">See Also</h2><ul><li>To get a head start with a more "batteries-included" project
template, see <a href="http://www.luminusweb.net/">Luminus</a>.</li></ul><h2 id="contributors">Contributors</h2><p>John Gabriele <a href="mailto:jmg3000@gmail.com">jmg3000@gmail.com</a> (original author)</p><p>Ivan Kryvoruchko <a href="mailto:gildraug@gmail.com">gildraug@gmail.com</a></p><p>Sean Corfield <a href="mailto:sean@corfield.org">sean@corfield.org</a></p>
<div id="prev-next">
<a href="../eclipse/index.html">&laquo; Starting with Eclipse and Counterclockwise For Clojure Development</a>
||
<a href="../parsing_xml_with_zippers/index.html">Parsing XML in Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="index.html">Basic Web Development</a></li>
<li><a href="../parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,250 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Starting with Eclipse and Counterclockwise For Clojure Development</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/tutorials/eclipse/" />
<meta property="og:title" content="Starting with Eclipse and Counterclockwise For Clojure Development" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/tutorials/eclipse/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Starting with Eclipse and Counterclockwise For Clojure Development</h2>
</div>
<p>This guide covers:</p><ul><li>Installing Eclipse</li><li>Installing Counterclockwise, the Clojure plugin for Eclipse</li><li>Creating a sample project</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
(including images &amp; stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.4.</p><h2 id="installing-eclipse">Installing Eclipse</h2><ol><li>Download the latest release of Eclipse from the <a href="http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/junor">official site</a>.</li><li>Install Counterclockwise plugin.
<ol><li>navigate to the "Install new Software" tab under the help menu</li><li>paste in the CCW update URL: http://ccw.cgrand.net/updatesite in the "Work with:" text field</li><li>check the "Clojure Programming" checkbox and hit the "Next" button</li></ol></li><li>Follow the instructions on the screen and restart Eclipse for changes to take effect.</li></ol><p>Counterclockwise takes care of setting up Clojure and Leiningen for you. And once the plugin is installed, you will be
able to create a new Clojure project or a new Leiningen project.</p><p>Clojure project will use Eclipse to manage dependencies, while the Leiningen project will pull dependencies from the
<code>project.clj</code> in the root folder of the project.</p><p>At this point you should have Eclipse with CCW up and running. Navigate to File-&gt;new-&gt;project in Eclipse menu.
Then select Leiningen-&gt;Leiningen project. Here you'll see the default Leiningen Template filled in.
And only thing you have to do is provide a project name. Give the project a name and hit the finish button.</p><p>You should now see a new project in your Package Explorer view on the left. If you created a project called
<code>myproject</code> then the project template will have a src folder which will contain the package folder named myproject.</p><p>Note that since Java cannot use dashes in names, all the dashes in package folders for namespaces get converted to underscores.
The package will contain a core.clj file, and its contents should look like the following:</p><pre><code class="clojure">(ns myproject.core)
(defn foo
"I don't do a whole lot."
[x]
(println x "Hello, World!"))
</code></pre><p>Let's open it and then hit the run button. You should see a REPL pop up momentarily on the bottom of the IDE.
If all went well, your project should be ready to work on (if it failed, see the <a href="index.html#troubleshooting">troubleshooting section</a>). The code that's in the file will have already been
loaded up in the REPL when we hit run, and we should now be able to call our foo function.</p><p>To do that, let's write the code which calls foo below it:</p><pre><code class="clojure">(foo "Test: ")
</code></pre><p>Then navigate the cursor inside the call body and hit CTRL+ENTER on Linux/Windows or CMD+ENTER on OS X.
You should see "Hello, World!" printed in the REPL view on the bottom. We can now change the behavior of the
<code>foo</code> function and after reloading it the new behavior will be available next time it's called.</p><p>It's also recommended to enable the "strict/paredit" mode under Preferences-&gt;Clojure-&gt;Editor section.
This will allow the editor to keep track of balancing the parens for you.</p><p>Another useful feature of the editor is the ability to select code by expression.
If you navigate inside a function and press ALT+SHIFT+UP (use CMD instead of ALT in OS X), then inner
body of the expression will be selected, pressing it again, will select the expression, and then the outer body,
and so on. Conversely pressing ALT+SHIFT+DOWN will narrow the selection. This allows you to quickly navigate nested
structures, and select code by chunks of logic as opposed to simply selecting individual lines.</p><h2 id="managing-dependencies">Managing dependencies</h2><h3 id="eclipse-dependencies">Eclipse Dependencies</h3><ol><li>Right click on the project navigate to properties.</li><li>Under properties select "Java Build Path"</li><li>Under Libraries select "Add External JARs..."</li><li>Click OK</li></ol><p>The library will show up under "Referenced Libraries" in Package Explorer.</p><h3 id="leiningen">Leiningen</h3><p>You will also see a <code>project.</code>clj` file in the root of the project. This file should look like the following:</p><pre><code class="clojure">(defproject myproject "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.4.0"]])
</code></pre><p>You can add new dependencies to your project by adding them to the dependencies vector.
For example, if we wanted to add an HTTP client, head to <a href="http://clojuresphere.herokuapp.com/">ClojureSphere</a>
and navigate to the clj-http page.</p><p>From there follow the link to Clojars and copy the following:</p><pre><code class="clojure">[clj-http "0.6.4"]
</code></pre><p>now we'll simply paste it under dependencies in our <code>project.clj</code>:</p><pre><code class="clojure">:dependencies [[org.clojure/clojure "1.4.0"]
[clj-http "0.6.4"]]
</code></pre><p>In the package explorer view on the left expand "Leiningen dependencies"
and see that the clj-http jar included there. You will now have to kill our current REPL
if it is running. To do that navigate to the terminal view next to it and press the stop button.
When we start a new instance of the REPL, the library will be available for use.</p><p>In the core file we can now require the library in the namespace definition:</p><pre><code class="clojure">(ns myproject.core
(:require [clj-http.client :as client]))
</code></pre><p>and test using the client by typing</p><pre><code class="clojure">(client/get "http://google.com")
</code></pre><p>and running it as we did earlier.</p><h2 id="troubleshooting">Troubleshooting</h2><p>If when you attempt to run your code for the first time, you are asked
to select a way to run your project, rather than it just running, you
can try right clicking on the root project folder and then selecting
Leiningen-&gt;Reset Project Configuration.</p>
<div id="prev-next">
<a href="../vim_fireplace/index.html">&laquo; Clojure with Vim and fireplace.vim</a>
||
<a href="../basic_web_development/index.html">Basic Web Development &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,445 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Clojure with Emacs</title>
<meta name="description" content="This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.What Version of Clojure Does This Guide Cover?">
<meta property="og:description" content="This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.What Version of Clojure Does This Guide Cover?">
<meta property="og:url" content="https://clojure-doc.github.io/articles/tutorials/emacs/" />
<meta property="og:title" content="Clojure with Emacs" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/tutorials/emacs/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Clojure with Emacs</h2>
</div>
<p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.5+ and Emacs 24+ for MS Windows and Linux,
and Emacs 26+ for macOS. Earlier Clojure and Emacs releases
are not supported by these instructions.</p><h2 id="overview">Overview</h2><p>Emacs has traditionally been one of the best development environments
for functional languages and Lisps in particular. This guide will
explain how to get it installed, and give an example of a basic
workflow to use while developing a simple library.</p><h2 id="installing-emacs">Installing Emacs</h2><h3 id="macos">macOS</h3><p>The easiest way to get going with Emacs on macOS is to
use <a href="https://brew.sh">Homebrew</a>. Instructions for installing Homebrew
are provided on the landing page, and requirements (such as Xcode) are
listed on the <a href="https://docs.brew.sh/Installation">installation details</a>
page.</p><p>Once brew is installed, you can install Emacs using:</p><pre><code class="bash">$ brew cask install emacs
</code></pre><p>This will install Emacs into your <code>/Applications/Emacs.app</code> folder and
provide a symlink to the application as <code>/usr/local/bin/emacs</code>.</p><p>After installing, Emacs can be launched the same as other Mac applications
<em>or</em> from the terminal via:</p><pre><code class="bash">$ emacs
</code></pre><h3 id="debianubuntu">Debian/Ubuntu</h3><p>Newer Debian-based systems (post-wheezy) ship Emacs 24 in apt:</p><pre><code class="bash">$ sudo apt install emacs24
</code></pre><h3 id="archantergos">Arch/Antergos</h3><p>The latest version of Emacs(<em>i.e.</em> v25.1) is available in Arch's official repositories.</p><pre><code class="bash">$ sudo pacman -S emacs
</code></pre><p>On older systems you can add unofficial package sources for <code>emacs-snapshot</code>,
either for <a href="http://emacs.naquadah.org/">Debian</a> or
<a href="https://launchpad.net/~cassou/+archive/emacs">Ubuntu</a>.</p><h3 id="ms-windows">MS Windows</h3><p>You can find Emacs for Windows in the <a href="http://ftp.gnu.org/pub/gnu/emacs/windows/">FSF FTP
directory</a>.</p><p>Download the file named <code>emacs-24.1-bin-i386.zip</code> and unzip it in a new folder.
Avoid folder with spaces in their names such as <code>C:\Documents and Settings</code>.
Prefer folder names such as <code>C:\emacs-24.1</code>.</p><p><a href="http://support.microsoft.com/kb/310519#tocHeadRef">Create an environment variable</a>
with name HOME and value equal to the location of your home folder; in Windows
XP, it's <code>C:\Documents and Settings\YourUsername</code>, in Windows 7, it's
<code>C:\Users\YourUsername</code>. With this variable set, you can use the tilde character
(<code>~</code>) to type the name of a file under your home folder and Emacs will expand
its full path.</p><p>The following section describes Emacs configuration using the folder <code>.emacs.d</code>.
When using Emacs in Windows, you should create this folder under your home
folder. In Windows XP, that will be the folder <code>C:\Documents and Settings\YourUsername\.emacs.d</code>; in Windows 7, that will be the folder
<code>C:\Users\YourUsername\.emacs.d</code>.</p><h2 id="configuring-emacs">Configuring Emacs</h2><p>So Emacs is installed, but running it now would be a somewhat
barebones experience and not particularly useful for Clojure
development.</p><h3 id="manual-setup">Manual setup</h3><p>Emacs can be configured through a folder in your home folder called
<a href="http://www.emacswiki.org/emacs/DotEmacsDotD">~/.emacs.d</a>, and
configuration options are pretty much endless. To help you through
this, Phil Hagelberg has created a small library enables a few
non-intrusive helpful features called
<a href="https://github.com/technomancy/better-defaults">better-defaults</a>
which might be useful if you are not already an Emacs pro.</p><p>Most Emacs packages are kept at <a href="http://melpa.milkbox.net">MELPA</a>,
the community package host. Add this code to your config in
<code>~/.emacs.d/init.el</code> to tell Emacs to look there:</p><p>For the stable repository:</p><pre><code class="cl">(require 'package)
(add-to-list 'package-archives
'("melpa-stable" . "http://stable.melpa.org/packages/") t)
(package-initialize)
</code></pre><p>For the latest packages:</p><pre><code class="cl">(require 'package)
(add-to-list 'package-archives
'("melpa" . "http://melpa.org/packages/") t)
(package-initialize)
</code></pre><p>Run <code>M-x package-refresh-contents</code> to pull in the package listing.</p><p><code>M-x</code> means <code>meta-x</code>, and meta is mapped to the alt key on most keyboards,
though Mac OS X usually maps it to the command key.</p><p>You'll need to install the following packages:</p><ul><li><a href="https://github.com/clojure-emacs/clojure-mode">clojure-mode</a> - a major mode for editing Clojure and ClojureScript code</li><li><a href="https://github.com/clojure-emacs/cider">CIDER</a> - a Clojure interactive development environment and REPL for Emacs</li><li><a href="https://github.com/bbatsov/projectile">projectile</a>(optional) - for navigating inside your projects swiftly</li></ul><p>Before continuing any further you should briefly consult their documentation.</p><p>You can either install each package one-by-one with <code>M-x package-install</code> or specify all your packages in Emacs Lisp as part of
your configuration file. This is helpful if you take your dotfiles to
a new machine; you don't have to remember everything you've installed
by hand.</p><pre><code class="cl">(defvar my-packages '(better-defaults
projectile
clojure-mode
cider))
(dolist (p my-packages)
(unless (package-installed-p p)
(package-install p)))
</code></pre><p>Put the code above in <code>~/.emacs.d/init.el</code> and run it with <code>M-x eval-buffer</code>.</p><p>A lot of warnings will likely whizz by as it installs and compiles
packages. Unless you have any actual <em>errors</em> this is all fine.</p><p>To look at the other packages available for installation you can
invoke <code>M-x package-list-packages</code>. To manually install a package,
move the point to line of the package with the keyboard and press 'i'
for 'install'. After selecting all the packages you are interested in,
press 'x' for 'eXecute' to install.</p><h3 id="preconfigured-setup">Preconfigured setup</h3><p>There are also some ready-made Emacs configurations that are optimized
for Clojure development -
<a href="https://github.com/bbatsov/prelude">Prelude</a>(developed by the
maintainer of CIDER and clojure-mode) and
<a href="https://github.com/overtone/emacs-live">Emacs Live</a>.</p><p>If you want a more powerful Emacs setup you should definitely check them out.</p><h3 id="basics">Basics</h3><p>The first thing you should do without question, is to go through the
built-in Emacs tutorial. To do this press <code>C-h t</code> or hold down Control
and press <code>h</code> and then press <code>t</code> by itself.</p><p>With that in mind, these are the basic keystrokes you're going to be
using most often with the default binary of Emacs 24+:</p><pre><code>File/buffer/window commands
C-x C-f Find file
C-x C-s Save buffer
C-x s Save file (like save-as)
C-x b Switch buffer
C-x k Kill buffer
C-x 1 Delete other windows
C-x 0 Delete current window
C-x 2 Split window horizontally
C-x 3 Split window vertically
Movement commands
C-a Beginning of line
C-e End of line
C-n Next line (down)
C-p Previous line (up)
C-b Back (left)
C-f Forward (right)
M-f Forward a word
M-b Back a word
C-v Forward a page
M-v Back a page
Edit commands
C-d Kill character
M-d Kill word
M-delete Kill word backwards
Misc commands
C-s Regex search forwards
C-r Regex search backwards
M-% Query replace
</code></pre><p>I should also mention the help commands:</p><pre><code>C-h t Tutorial (goes over the basics)
C-h b Describe all current key bindings
C-h m Describe the current mode
C-h a Apropos - search the help for a term
C-h k Describe key
</code></pre><p>I recommend going through the tutorial at least once as it will give
you a good understanding of the navigation and movement commands.
Another useful command you will use a lot is <code>M-x</code> which allows you to
run any command. And there are a LOT. Apropos is very useful for
searching for something <code>C-h a</code>.</p><p>So after doing the tutorial (you did do that, RIGHT? O_O) you can move
around, open files, save files, etc., and are generally comfortable at
the basics. There is an almost infinite amount of things to learn
about Emacs, but those basics will get you a long way.</p><h2 id="creating-a-project">Creating a project</h2><p>Let's go through the process of creating a small sample clojure project
and illustrate how Emacs helps makes us champions in the land of lisp.</p><p>The project we will be building is a trivially simple command line
parser that will take the argument pairs given to it and turn them
into a map of key-value pairs. The functionality is irrelevant and not
particularly useful. It serves purely to illustrate the development
flow.</p><p>If you don't have <a href="http://leiningen.org">Leiningen</a> yet, get it
installed and then use it to create a new project:</p><pre><code class="bash">$ lein new command-line-args
$ cd command-line-args
</code></pre><p>Take a look at the project structure:</p><pre><code>+ doc
- intro.md
- project.clj
- README.md
+ src
+ command_line_args
- core.clj
+ test
+ command_line_args
- core_test.clj
</code></pre><p>Should be fairly self-explanatory, though Leiningen's built-in tutorial
(available via <code>lein help tutorial</code>) provides a detailed explanation of
the project structure.</p><p>Let's start up a live REPL session.</p><pre><code>M-x cider-jack-in
</code></pre><p>This should open up a new window looking at our <code>*cider-repl*</code> buffer.</p><p>First thing to do is add a simple test (in fact the only test we will
be adding because by default, we get it right first time). Open the
<code>core_test.clj</code> file inside of the test folder. Replace the test that
is there with the following:</p><pre><code class="clojure">(deftest pairs-of-values
(let [args ["--server" "localhost"
"--port" "8080"
"--environment" "production"]]
(is (= {:server "localhost"
:port "8080"
:environment "production"}
(parse-args args)))))
</code></pre><p>We are simply assigning a list of arguments as they would arrive from
the command line to a local called args, and asserting that the
return value from a function called <code>parse-args</code> is equal to those
command line args turned into a simple map.</p><p>Compile the file with <code>C-c C-k</code>(<code>M-x cider-load-buffer</code>). We should get an error
message at the bottom of the emacs window complaining that clojure can't find
parse-args. Let's try to fix the exception by opening <code>core.clj</code> (<code>C-x C-f</code>/<code>M-x find-file</code>) and adding the following definition:</p><pre><code class="clojure">(defn parse-args [args]
{})
</code></pre><p>Compile this with <code>C-c C-k</code>, save it (<code>C-x C-s</code>/<code>M-x save-buffer</code>), switch back
to the test buffer (<code>C-x b RET</code>/<code>M-x switch-to-buffer RET</code>) and try compiling
again (<code>C-c C-k</code>). This time it will succeed, so try running the tests with
<code>C-c C-t t</code>(<em>i.e</em> <code>M-x cider-test-run-test</code>) and you should get a test report
buffer showing some failure information:</p><pre><code class="clojure">(not (= {:server "localhost",
:port "8080",
:environment "production"}
{}))
</code></pre><p>Anyway, our map was empty as expected. Let's fix that:</p><pre><code class="clojure">(defn parse-args [args]
(apply hash-map args))
</code></pre><p>Running our tests again we now get another error:</p><pre><code class="clojure">(not (= {:server "localhost",
:port "8080",
:environment "production"}
{"--port" "8080",
"--server" "localhost",
"--environment" "production"}))
</code></pre><p>Whoops, our keys are just strings with the dashes still in place. We
need to strip those off and turn them into keywords:</p><pre><code class="clojure">(defn parse-args [args]
(into {} (map (fn [[k v]] [(keyword (.replace k "--" "")) v])
(partition 2 args))))
</code></pre><p>And re-running the tests in the test buffer we are all happy. If we
had multiple test files we can run them all from the CLI using:</p><pre><code class="bash">$ lein test
</code></pre><p>Re-running all the tests from Leiningen can be a good sanity check
before you wrap up work on a feature or branch since there are some
cases where developing from a REPL can give misleading results. For
instance, if you delete a function definition but still call it from
other functions, you won't notice until your process is restarted.</p><p>So that is an extremely simple example of a workflow using Emacs with
<code>clojure-mode</code> and <code>cider-test</code>.</p><h2 id="using-the-repl">Using the REPL</h2><p>One thing we haven't looked at is how useful having an open running
REPL in Emacs can be for development. If you still have your project
open, split the window (<code>C-x 2</code> (horizontally) or <code>C-x 3</code> (vertically)) in
two so you have the <code>core.clj</code> and <code>*cider-repl*</code> buffers open.
Let's say you are editing the core.clj and you want to play around with
the functions as you define them. Looking at <code>parse-args</code> you have
decided you want to pull out the anonymous function to be a named
function <code>keywordize</code>.</p><p>First load and compile the buffer into the REPL process with <code>C-c C-k</code>. Change the namespace of the REPL buffer to the one of the file
you're in with <code>C-c M-n</code>. Now switch to the REPL window with <code>C-x o</code>.</p><p>You now have access to the functions in this namespace that were
defined when you compiled the file. Try it:</p><pre><code>command-line-args.core&gt; (parse-args '("key" "value"))
{:key "value"}
</code></pre><p>Let's go ahead and create our new function in <code>core.clj</code>:</p><pre><code class="clojure">(defn keywordize [kvp]
(let [[k v] kvp]
[(keyword (.replace k "--" "")) v]))
(defn parse-args [args]
(into {} (map keywordize (partition 2 args))))
</code></pre><p>Now we have a couple of options, we could re-compile the whole file again
(<code>C-c C-k</code>) or we could evaluate each function on its own by going to the end
of the s-exp and using <code>C-x C-e</code>(<em>i.e.</em> <code>cider-eval-last-sexp</code>) which sends the
s-exp to the running REPL. Now switching back to the core.clj namespace
(<code>C-c M-n</code>) and switching back to the REPL buffer we can try out our
<code>keywordize</code> function:</p><pre><code>command-line-args.core&gt; (keywordize ["--oh" "hai"])
[:oh "hai"]
</code></pre><p>If your REPL is starting to get cluttered you can <code>M-x cider-repl-clear-buffer</code>
to clear by first switching to the REPL buffer. The ability to continually
change the code and play around with it is one of the things that makes Emacs
and a lisp a great combination for development.</p><p>If you find yourself wanting to repeat a command you just typed at the
REPL, you can use <code>M-p</code> scroll back through history and <code>M-n</code> to go
forwards. Also, all of the Emacs editing commands are available in the
REPL, which is great.</p><p>A handy clojure function to use in the REPL is <code>clojure.repl/doc</code> which
gives you the docstring for a given function:</p><pre><code>command-line-args.core&gt; (use 'clojure.repl)
nil
command-line-args.core&gt; (doc println)
-------------------------
clojure.core/println
([&amp; more])
Same as print followed by (newline)
nil
</code></pre><p>However there is a shortcut <code>C-c C-d d</code> when your cursor is over a
function name. This will show the Clojure (or Javadoc) doc in a new window. If
instead you want to jump to the source of the function you can use
<code>M-.</code>, which is awesome. This works on your own functions as well as
those which come from third-party libraries. Use <code>M-,</code> to pop the
stack and return to where you were. For all the definitions in a
single file you can use <code>M-x imenu</code> to list them and jump to one.</p><p>When you are finished with the REPL (or if for some reason it has
gotten into a bad state), you can simply kill the <code>*cider-repl*</code>
buffer by typing <code>M-x cider-quit</code> and re-run <code>cider-jack-in</code> to start another.</p><h2 id="appendix">Appendix</h2><p><a href="http://stable.melpa.org/#/getting-started">MELPA documentation</a></p><p>CIDER keyboard shortcuts can be found in <a href="https://github.com/clojure-emacs/cider#keyboard-shortcuts">CIDER documentation</a>.</p><h2 id="contributors">Contributors</h2><p><a href="http://blog.gaz-jones.com">Gareth Jones</a>, 2012 (original author)</p><p>Thanks to <a href="http://technomancy.us/">Phil Hagelberg</a>, <a href="http://cleancode.se/">Mikael
Sundberg</a>, and <a href="http://jakemccrary.com/">Jake
McCrary</a> for suggestions for improvements to
the original blog posts from which this guide was created.</p>
<div id="prev-next">
<a href="../introduction/index.html">&laquo; Introduction to Clojure</a>
||
<a href="../vim_fireplace/index.html">Clojure with Vim and fireplace.vim &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../introduction/index.html">Introduction to Clojure</a></li>
<li><a href="index.html">Clojure with Emacs</a></li>
<li><a href="../vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,256 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Getting Started with Clojure</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/tutorials/getting_started/" />
<meta property="og:title" content="Getting Started with Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/tutorials/getting_started/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Getting Started with Clojure</h2>
</div>
<p>This guide covers:</p><ul><li>prerequisites (such as Leiningen) and installing</li><li>running the REPL</li><li>creating a project</li><li>interactive development</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="overview">Overview</h2><p>Clojure is a wonderfully simple language and you are going to love
it.</p><p>To quickly get started, first make sure you've got Java installed.</p><p>Then install the <a href="http://leiningen.org/">Leiningen</a> project management
tool.</p><blockquote><p>This author (jg) recommends always installing by downloading the
script directly (as described in the instructions at leiningen.org),
rather than using your OS's package manager. This will ensure that
you get the latest lein version 2.</p></blockquote><p>Clojure programs are typically developed inside their own project
directory, and Leiningen manages projects for you. Lein takes care of
pulling in dependencies (including Clojure itself), running the REPL,
running your program and its tests, packaging your program for
distribution, and other administrative tasks. Run <code>lein help</code> to
see the list of all the tasks in can perform.</p><blockquote><p>Again, there's no need to "install" Clojure, per se. Lein
will take care of fetching it for you.</p></blockquote><h2 id="trying-out-the-repl">Trying out the REPL</h2><p>Although lein facilitates managing your projects, you can also run it
on its own (outside of any particular project directory). Once you
have the <code>lein</code> tool installed, run it from anywhere you like to get a
repl:</p><pre><code>$ lein repl
</code></pre><p>You should be greeted with a "<code>user=&gt;</code>" prompt. Try it out:</p><pre><code class="clojure">user=&gt; (+ 1 1)
;; ⇒ 2
user=&gt; (distinct [:a :b :a :c :a :d])
;; ⇒ (:a :b :c :d)
user=&gt; (dotimes [i 3]
#_=&gt; (println (rand-nth ["Fabulous!" "Marvelous!" "Inconceivable!"])
#_=&gt; i))
;; Marvelous! 0
;; Inconceivable! 1
;; Fabulous! 2
;; ⇒ nil
</code></pre><h2 id="your-first-project">Your first project</h2><p>Create your first Clojure program like so:</p><pre><code class="bash">lein new app my-proj
cd my-proj
# Have a look at the "-main" function in src/my_proj/core.clj.
lein run
</code></pre><p>and see the output from that <code>println</code> function call in
my_proj/core.clj!</p><h2 id="interactive-development">Interactive Development</h2><p>In your project directory, start up a repl (<code>lein repl</code>) and
run your <code>-main</code> function to see its output in the repl:</p><pre><code>$ lein repl
...
my-proj.core=&gt; (-main)
Hello, World!
nil
</code></pre><p>(The prompt is now "my-proj.core=&gt;" instead of "user=&gt;" because lein
has started the repl in an app project. More about that ("namespaces")
in the topical guides.)</p><p>From elsewhere, open up your my-proj/src/my_proj/core.clj file
in your editor. Modify the text in that <code>println</code> call.</p><p>Back in the repl, reload your source file and run <code>-main</code> again:</p><pre><code>my-proj.core=&gt; (require 'my-proj.core :reload)
my-proj.core=&gt; (-main)
</code></pre><p>to see your changes.</p><h2 id="see-also">See Also</h2><p>Other getting started documentation you might find useful:</p><ul><li><a href="http://yogthos.github.io/ClojureDistilled.html">Clojure Distilled</a>:
introduction to core concepts necessary for working with Clojure</li><li><a href="http://www.unexpected-vortices.com/clojure/brief-beginners-guide/index.html">A Brief Beginner's Guide to
Clojure</a>:
contains a bit more overview and background material for learning your way
around the landscape.</li><li><a href="https://cemerick.com/blog/2012/05/02/starting-clojure-mk-2.html">Starting Clojure screencast</a>:
an extensive getting-started screencast using Eclipse to develop a webapp project.</li></ul><h2 id="next-stop">Next Stop</h2><p>Next stop: <a href="../introduction/index.html">the basic Clojure language tutorial</a>.</p><h2 id="contributors">Contributors</h2><p>John Gabriele <a href="mailto:jmg3000@gmail.com">jmg3000@gmail.com</a> (original author)</p>
<div id="prev-next">
<a href="../../content/index.html">&laquo; Table of Contents</a>
||
<a href="../introduction/index.html">Introduction to Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="index.html">Getting Started with Clojure</a></li>
<li><a href="../introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

View file

@ -0,0 +1,385 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Growing a DSL with Clojure</title>
<meta name="description" content="Lisps like Clojure are well suited to creating rich DSLs that integrate seamlessly into the language.You may have heard Lisps boasting about code being data and data being code. In this article we will define a DSL that benefits handsomely from this fact.">
<meta property="og:description" content="Lisps like Clojure are well suited to creating rich DSLs that integrate seamlessly into the language.You may have heard Lisps boasting about code being data and data being code. In this article we will define a DSL that benefits handsomely from this fact.">
<meta property="og:url" content="https://clojure-doc.github.io/articles/tutorials/growing_a_dsl_with_clojure/" />
<meta property="og:title" content="Growing a DSL with Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/tutorials/growing_a_dsl_with_clojure/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Growing a DSL with Clojure</h2>
</div>
<p>Lisps like Clojure are well suited to creating rich DSLs that integrate seamlessly into the language.</p><p>You may have heard Lisps boasting about code being data and data being code. In this article we will define a DSL that benefits handsomely from this fact.</p><p>We will see our DSL evolve from humble beginnings, using successively more of Clojures powerful and unique means of abstraction.</p><h2 id="the-mission">The Mission</h2><p>Our goal will be to define a DSL that allows us to generate various scripting languages. The DSL code should look similar to regular Clojure code.</p><p>For example, we might use this Clojure form to generate either Bash or Windows Batch script output:</p><p>Input (Clojure form):</p><pre><code class="clojure">(if (= 1 2)
(println "a")
(println "b"))
</code></pre><p>Output (Bash script):</p><pre><code class="sh">if [ 1 -eq 2 ]; then
echo "a"
else
echo "b"
fi
</code></pre><p>Output (Windows Batch script):</p><pre><code class="bat">IF 1==2 (
ECHO a
) ELSE (
ECHO b
)
</code></pre><p>We might, for example, use this DSL to dynamically generate scripts to perform maintenance tasks on server farms.</p><h2 id="baby-steps-mapping-to-our-domain-language">Baby Steps: Mapping to Our Domain Language</h2><p>I like Bash, so lets start with a Bash script generator.</p><p>To start, we need to expose some parallels between Clojures core types and our domain language.</p><p>So which Clojure types have simple analogues in Bash script?</p><p>Strings and numbers should just simply return their String representation, so we will start with those.</p><p>Lets define a function <code>emit-bash-form</code> that takes a Clojure form and returns a string that represents the equivalent Bash script.</p><pre style="visibility:hidden; height:0;"><code class="klipse-clojure nohighlight">
(require '[chivorcam.core :refer [defmacro defmacfn]])
</code></pre><pre><code class="klipse-clojure nohighlight">(defn emit-bash-form [a]
"Returns a String containing the equivalent Bash script
to its argument."
(cond
(string? a ) a
(number? a) (str a)
:else (throw (ex-info "Fell through" a))))
</code></pre><p>The <code>cond</code> expression handles cases for strings and numbers or throws an exception.</p><pre><code class="klipse-clojure nohighlight">(emit-bash-form 1)
</code></pre><pre><code class="klipse-clojure nohighlight">(emit-bash-form "a")
</code></pre><pre><code class="klipse-clojure nohighlight">(emit-bash-form {})
</code></pre><p>Now if we want to add some more dispatches, we just need to add a new clause to our <code>cond</code> expression.</p><h2 id="echo-and-print">Echo and Print</h2><p>Lets add a feature.</p><p>Bash prints to the screen using <code>echo</code>. Youve probably seen it if youve spent any time with a Linux shell.</p><pre><code class="sh">ambrose@ambrose-desktop&gt; echo asdf
asdf
</code></pre><p>clojure.core also contains a function <code>println</code> that has similar semantics to Bash's <code>echo</code>.</p><pre><code class="klipse-clojure nohighlight">(println "asdf")
</code></pre><p>Wouldnt it be cool if we could pass <code>(println "a")</code> to <code>emit-bash-form</code>?</p><pre><code class="clojure">(emit-bash-form (println "asdf"))
</code></pre><p>At first, this seems like asking the impossible.</p><p>To made an analogy with Java, imagine calling this Java code and expecting the first argument to equal <code>System.out.println("asdf")</code>.</p><pre><code class="java">foo( System.out.println("asdf") );
</code></pre><p>(Lets ignore the fact that <code>System.out.println(...)</code> returns a void).</p><p>Java evaluates the arguments before you can even blink, resulting in a function call to println. How can we stop this evaluation and return the raw code?</p><p>Indeed this is an impossible task in Java. Even if this were possible, what could we expect do with the raw code?(!)</p><p><code>System.out.println("asdf")</code> is not a Collection, so we cant iterate over it; it is not a <code>String</code>, so we cant partition it with regular expressions.</p><p>Whatever "type" the raw code <code>System.out.println("asdf")</code> has, its not meant to be known by anyone but compiler writers.</p><p>Lisp turns this notion on its head.</p><h2 id="lisp-code-is-data">Lisp Code Is Data</h2><p>A problem with raw code forms in Java (assuming it is possible to extract them) is the lack of facilities to interrogate them. How does Clojure get around this limitation?</p><p>To get to the actual raw code at all, Clojure provides a mechanism to stop evaluation via quote. Prepending a quote to a code form prevents its evaluation and returns the raw Clojure form.</p><pre><code class="klipse-clojure nohighlight">'(println "a")
</code></pre><p>So what is the type of our result?</p><pre><code class="klipse-clojure nohighlight">(type '(println "a"))
</code></pre><p>It's a list!</p><p>We can now interrogate the raw code as if it were any old Clojure list (because it is!).</p><pre><code class="klipse-clojure nohighlight">(first '(println "a"))
</code></pre><pre><code class="klipse-clojure nohighlight">(second '(println "a"))
</code></pre><p>This is a result of Lisps remarkable property of code being data.</p><h2 id="a-little-closer-to-clojure">A Little Closer to Clojure</h2><p>Using quote, we can get halfway to a DSL that looks like Clojure code.</p><pre><code class="clojure">(emit-bash-form
'(println "a"))
</code></pre><p>Lets add this feature to <code>emit-bash-form</code>. We need to add a new clause to the <code>cond</code> form. Which type should the dispatch value be?</p><p>So lets add a clause for lists.</p><pre><code class="klipse-clojure nohighlight">(defn emit-bash-form [a]
"Returns a String containing the equivalent Bash script
to its argument."
(cond
(list? a)
(case (name (first a))
"println" (str "echo " (second a)))
(string? a) a
(number? a) (str a)
:else (throw (ex-info "Fell through" a))))
</code></pre><p>As long as we remember to quote the argument, this is not bad.</p><pre><code class="klipse-clojure nohighlight">(emit-bash-form '(println "a"))
</code></pre><pre><code class="klipse-clojure nohighlight">(emit-bash-form '(println "hello"))
</code></pre><h2 id="multimethods-to-abstract-the-dispatch">Multimethods to Abstract the Dispatch</h2><p>Weve made a good start, but I think its time for some refactoring.</p><p>Currently, to extend our implementation we add to our function emit-bash-form. Eventually this function will be too large to manage; we need a mechanism to split this function into more manageable pieces.</p><p>Essentially emit-bash-form is dispatching on the type of its argument. This dispatch style is a perfect fit for an abstraction Clojure provides called a multimethod.</p><p>Lets define a multimethod called <code>emit-bash</code>.</p><p>The multimethod handles dispatch in a similar way to <code>cond</code>, but without having to actually write each case. Lets compare this multimethod with our previous <code>cond</code> expression. <code>defmulti</code> is used to create a new multimethod, and associates it with a dispatch function.</p><pre><code class="klipse-clojure nohighlight">(defmulti emit-bash
(fn [form]
(cond
(list? form) :list
(string? form) :string
(number? form) :number
:else (throw (ex-info "Unknown type" form)))))
</code></pre><p><code>defmethod</code> is used to add <em>methods</em> to an existing multimethod. Here <code>:string</code> is the <em>dispatch value</em>, and the method returns the form as is.</p><pre><code class="klipse-clojure nohighlight">(defmethod emit-bash
:string
[form]
form)
</code></pre><p>Similar for numbers and lists:</p><pre><code class="klipse-clojure nohighlight">(defmethod emit-bash
:number
[form]
(str form))
(defmethod emit-bash
:list
[form]
(case (name (first form))
"println" (str "echo " (second form))))
</code></pre><p>Adding new methods has the same result as extending our <code>cond</code> expression, except:</p><ul><li>multimethods handle the dispatch, instead of writing it manually</li><li>anyone can extend the multimethod at any point, without disturbing existing code</li></ul><p>So how can we use <code>emit-bash</code>? Calling a multimethod is just like calling any Clojure function.</p><pre><code class="klipse-clojure nohighlight">(emit-bash '(println "a"))
</code></pre><p>The dispatch is silently handled under the covers by the multimethod.</p><h2 id="extending-our-dsl-for-batch-script">Extending our DSL for Batch Script</h2><p>Lets say Im happy with the Bash implementation. I feel like starting a new implementation that generates Windows Batch script. Lets define a new multimethod, emit-batch.</p><pre><code class="klipse-clojure nohighlight">(defmulti emit-batch
(fn [form]
(cond
(list? form) :list
(string? form) :string
(number? form) :number
:else (throw (ex-info "Unknown type" form)))))
(defmethod emit-batch
:list
[form]
(case (name (first form))
"println" (str "ECHO " (second form))
nil))
(defmethod emit-batch
:string
[form]
form)
(defmethod emit-batch
:number
[form]
(str form))
</code></pre><p>We can now use <code>emit-batch</code> and <code>emit-bash</code> when we want Batch and Bash script output respectively.</p><pre><code class="klipse-clojure nohighlight">(emit-batch '(println "a"))
</code></pre><pre><code class="klipse-clojure nohighlight">(emit-bash '(println "a"))
"echo a"
</code></pre><h2 id="ad-hoc-hierarchies">Ad-hoc Hierarchies</h2><p>Comparing the two implementations reveals many similarities. In fact, the only dispatch that differs is clojure.lang.PersistentList!</p><p>Some form of implementation inheritance would come in handy here.</p><p>We can tackle this with a simple mechanism Clojure provides to define global, ad-hoc hierarchies.</p><p>When I say this mechanism is simple, I mean non-compound; inheritance is not compounded into the mechanism to define classes or namespaces but rather is a separate functionality.</p><p>Contrast this to languages like Java, where inheritance is tightly coupled with defining a hierarchy of classes.</p><p>We can derive relationships from names to other names, and between classes and names. Names can be symbols or keywords. This is both very general and powerful!</p><p>We will use <code>(derive child parent)</code> to establishes a parent/child relationship between two keywords. <code>isa?</code> returns <code>true</code> if the first argument is derived from the second in a global hierarchy.</p><pre><code class="klipse-clojure nohighlight">(derive ::child ::parent)
(isa? ::child ::parent)
</code></pre><p>Lets define a hierarchy in which the Bash and Batch implementations are siblings.</p><pre><code class="klipse-clojure nohighlight">(derive ::bash ::common)
(derive ::batch ::common)
</code></pre><p>Lets test this hierarchy.</p><pre><code class="klipse-clojure nohighlight">(parents ::bash)
</code></pre><pre><code class="klipse-clojure nohighlight">(parents ::batch)
</code></pre><h2 id="utilizing-a-hierarchy-in-a-multimethod">Utilizing a Hierarchy in a Multimethod</h2><p>We can now define a new multimethod emit that utilizes our global hierarchy of names.</p><pre><code class="klipse-clojure nohighlight">(defmulti emit
(fn [form]
[*current-implementation*
(cond
(list? form) :list
(string? form) :string
(number? form) :number
:else (throw (ex-info "Unknown type" form)))]))
</code></pre><p>The dispatch function returns a vector of two items: the current implementation (either <code>::bash</code> or <code>::batch</code>), and the class of our form (like <code>emit-bash</code>'s dispatch function).</p><p><code>*current-implementation*</code> is a dynamic var, which can be thought of as a thread-safe global variable.</p><pre><code class="klipse-clojure nohighlight">(def ^{:dynamic true}
;; The current script language implementation to generate
*current-implementation*)
</code></pre><p>In our hierarchy, <code>::common</code> is the parent, which means it should provide the methods in common with its children. Let's fill in these common implementations.</p><p>Remember the dispatch value is now a vector, notated with square brackets. In particular, in each defmethod the first vector is the dispatch value (the second vector is the list of formal parameters).</p><pre><code class="klipse-clojure nohighlight">(defmethod emit [::common :string]
[form]
form)
(defmethod emit [::common :number]
[form]
(str form))
</code></pre><p>This should look familiar. The only methods that needs to be specialized are those for clojure.lang.PersistentList, as we identified earlier. Notice the first item in the dispatch value is <code>::bash</code> or <code>::batch</code> instead of <code>::common</code>.</p><pre><code class="klipse-clojure nohighlight">(defmethod emit [::bash :list]
[form]
(case (name (first form))
"println" (str "echo " (second form))
nil))
(defmethod emit [::batch :list]
[form]
(case (name (first form))
"println" (str "ECHO " (second form))
nil))
</code></pre><p>The <code>::common</code> implementation is intentionally incomplete; it merely exists to manage any common methods between its children.</p><p>We can test emit by rebinding <code>*current-implementation*</code> to the implementation of our choice with binding.</p><pre><code class="klipse-clojure nohighlight">(binding [*current-implementation* ::common]
(emit "a"))
</code></pre><pre><code class="klipse-clojure nohighlight">(binding [*current-implementation* ::batch]
(emit '(println "a")))
</code></pre><pre><code class="klipse-clojure nohighlight">(binding [*current-implementation* ::bash]
(emit '(println "a")))
</code></pre><pre><code class="klipse-clojure nohighlight">(binding [*current-implementation* ::common]
(emit '(println "a")))
</code></pre><p>Because we didnt define an implementation for <code>[::common :list]</code>, the multimethod falls through and throws an Exception.</p><p>Multimethods offer great flexibility and power, but with power comes great responsibility. Just because we can put our multimethods all in one namespace doesnt mean we should. If our DSL becomes any bigger, we would probably separate all Bash and Batch implementations into individual namespaces.</p><p>This small example, however, is a good showcase for the flexibility of decoupling namespaces and inheritance.</p><h2 id="icing-on-the-cake">Icing on the Cake</h2><p>Weve built a nice, solid foundation for our DSL using a combination of multimethods, dynamic vars, and ad-hoc hierarchies, but its a bit of a pain to use.</p><pre><code class="klipse-clojure nohighlight">(binding [*current-implementation* ::bash]
(emit '(println "a")))
</code></pre><p>Lets eliminate the boilerplate. But where is it?</p><p>The binding expression is an good candidate. We can reduce the chore of rebinding <em>current-implementation</em> by introducing with-implementation (which we will define soon).</p><pre><code class="clojure">(with-implementation ::bash
(emit '(println "a")))
</code></pre><p>Thats an improvement. But theres another improvement thats not as obvious: the quote used to delay our forms evaluation. Lets use script, which we will define later, to get rid of this boilerplate:</p><pre><code class="clojure">(with-implementation ::bash
(script
(println "a")))
</code></pre><p>This looks great, but how do we implement script? Clojure functions evaluate all their arguments before evaluating the function body, exactly the problem the quote was designed to solve.</p><p>To hide this detail we must wield one of Lisps most unique forms: the macro.</p><p>The macros main drawcard is that it doesnt implicitly evaluate its arguments. This is a perfect fit for an implementation of script.</p><pre><code class="klipse-clojure nohighlight">(defmacro script [form]
`(emit '~form))
</code></pre><p>To get an idea what is happening, heres what a call to script returns and then implicitly evaluates.</p><pre><code class="klipse-clojure nohighlight">(macroexpand '(script (println "a")))
</code></pre><p>It isnt crucial that you understand the details, rather appreciate the role that macros play in cleaning up the syntax.</p><p>We will also implement with-implementation as a macro, but for different reasons than with script. To evaluate our script form inside a binding form we need to drop it in before evaluation.</p><pre><code class="klipse-clojure nohighlight">(defmacro with-implementation
[impl &amp; body]
`(binding [cljs.user/*current-implementation* ~impl]
~@body))
</code></pre><p>Roughly, here is the lifecyle of our DSL, from the sugared wrapper to our unsugared foundations.</p><pre><code class="clojure">(with-implementation ::bash
(script
(println "a")))
=&gt;
(with-implementation ::bash
(emit
'(println "a"))
=&gt;
(binding [*current-implementation* ::bash]
(emit
'(println "a")))
</code></pre><p>Let's see it in action for Bash:</p><pre><code class="klipse-clojure nohighlight">(with-implementation ::bash
(script
(println "a")))
</code></pre><p>And for Windows:</p><pre><code class="klipse-clojure nohighlight">(with-implementation ::batch
(script
(println "a")))
</code></pre><p>Its easy to see how a few well-placed macros can put the sugar on top of strong foundations. Our DSL really looks like Clojure code!</p><h2 id="conclusion">Conclusion</h2><p>We have seen many of Clojures advanced features working in harmony in this DSL, even though we incrementally incorported many of them. Generally, Clojure helps us switch our implementation strategies with minimum fuss.</p><p>This is notable when you consider how much our DSL evolved.</p><p>We initially used a simple <code>cond</code> expression, which was converted into two multimethods, one for each implementation. As multimethods are just ordinary functions, the transition was seamless for any existing testing code. (In this case I renamed the function for clarity).</p><p>We then merged these multimethods, utilizing a global hierachy for inheritance and dynamic vars to select the current implementation.</p><p>Finally, we devised a pleasant syntactic interface with a two simple macros, eliminating that last bit of boilerplate that other languages would have to live with.</p><p>I hope you have enjoyed following the evolution of our little DSL. This DSL is based on a simplified version of <a href="https://github.com/pallet/stevedore">Stevedore</a> by <a href="http://hugoduncan.org/">Hugo Duncan</a>. If you are interested in how this DSL can be extended, you can do no better than browsing the source code of <a href="https://github.com/pallet/stevedore">Stevedore</a>.</p><h2 id="copyright">Copyright</h2><p>Copyright Ambrose Bonnaire-Sergeant, 2013</p>
<div id="prev-next">
<a href="../parsing_xml_with_zippers/index.html">&laquo; Parsing XML in Clojure</a>
||
<a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
<link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">
<script>
window.klipse_settings = {
"selector" : ".klipse-clojure"
};
</script>
<script src="https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"></script>
</body>
</html>

View file

@ -0,0 +1,968 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Introduction to Clojure</title>
<meta name="description" content="This guide covers:">
<meta property="og:description" content="This guide covers:">
<meta property="og:url" content="https://clojure-doc.github.io/articles/tutorials/introduction/" />
<meta property="og:title" content="Introduction to Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/tutorials/introduction/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Introduction to Clojure</h2>
</div>
<p>This guide covers:</p><ul><li>Clojure language basics</li><li>expressions, identifiers (locals, vars)</li><li><code>let</code> forms</li><li>scalars</li><li>functions</li><li>basic data types</li><li>introduction to immutable data structures</li><li>overview of Clojure reference types (vars, atoms, agents, refs)</li><li>looping and recursion</li><li>basics of Clojure macros</li></ul><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="overview">Overview</h2><p>This is a brief beginner's introduction to Clojure. If you haven't
already done so, have a look at the <a href="../getting_started/index.html">Getting
Started</a> tutorial. Before
continuing, make sure you've got Java and
<a href="http://leiningen.org">Leiningen</a> installed, and can create a new
project and run a REPL in it. The author expects you'll want to have a
REPL running while following this introduction so you can type
expressions into it as you go.</p><blockquote><p><strong>Note:</strong> In the code samples below, unless we're specifically
discussing the REPL, to reduce clutter we've usually omitted showing
the REPL prompt (ex. "<code>user=&gt;</code>" or "<code>my-proj.core=&gt;</code>").</p><p>Additionally: In Clojure, a semicolon begins a single-line comment,
and in this document we use "<code>; ⇒</code>" (for trailing comments) and
"<code>;; ⇒</code>" (for comments on their own line) to indicate what the
previous expression evaluates to.</p></blockquote><p>This introduction is a whirlwind tutorial of most of the basics of
Clojure. Its goal is to rapidly get you familiar with the core
areas of the language without wasting your time and also without getting
too bogged down in details or advanced topics (the various topics will
get more comprehensive coverage in the topic guides anyway).</p><p>As we said in the Getting Started tutorial, Clojure is a wonderfully
simple language, and you're going to love it.</p><h2 id="the-basics">The Basics</h2><p>Clojure is a general-purpose programming language, and a quite
practical one at that.</p><p>The syntax for Clojure is like Lisp and is very simple: code is made
up of expressions which are evaluated to some value. Here are some
examples of expressions:</p><pre><code class="clojure">5 ; ⇒ 5
"hi" ; ⇒ "hi"
[1 2 3] ; evaluates to the vector `[1 2 3]`
(+ 1 2) ; evaluates to the sum of 1 and 2
(if true "yes" "no") ; evaluates to the string "yes"
(println "hello!") ; evaluates to nil (but also prints "hello!")
</code></pre><p>Clojure supports a few extra bits of syntax which will be noted as we
encounter them.</p><p>Expressions can contain sub-expressions:</p><pre><code class="clojure">(+ 1
(* 2 3)
(/ 10 2)) ; ⇒ 1 + (2 * 3) + (10 / 2) = 12
</code></pre><p>Expressions in (various types of) brackets are often referred to as
"forms".</p><p>An expression in parentheses is usually treated as a function call,
but may also be a macro or special form (more about those in the
<a href="index.html#evaluation">Evaluation</a> section below).</p><p>Clojure is not whitespace-sensitive. Also, commas count as whitespace,
so you can omit them (for example, you can write a vector as <code>[1 2 3]</code>
instead of <code>[1, 2, 3]</code>).</p><p>Clojure code is block-structured and lexically scoped (though dynamic
scope is supported as well, if you really need it).</p><p>Clojure is a compiled language. The Clojure reader reads your source
code, then your code is compiled to JVM bytecode, and then it's run on
the JVM. The reader supports a few extra bits of syntactic sugar (for
example, a literal syntax for specifying regular expressions) that we
will cover as we go along.</p><p>Throughout this tutorial, we will liberally reference and lean on the
marvelous <a href="http://clojure.org/cheatsheet">Clojure Cheatsheet</a>. Aside
from being a great organizational aide, it also handily includes links
to the relevant <a href="http://clojuredocs.org/">Clojuredocs</a> pages where you
can find docs for and examples of the various Clojure functions.</p><p>In the REPL, at any time you can see the documentation for a given
function:</p><pre><code>(doc some-function)
</code></pre><p>and even the source code for it:</p><pre><code>(source some-function)
</code></pre><p>So, it will be of great use to you to have your REPL running so you
can try things out while following along.</p><h2 id="identifiers">Identifiers</h2><p>Identifiers are used to name things. For example, in</p><pre><code class="clojure">(def the-answer 42)
</code></pre><p>we've named something "the-answer" and given it the value 42.</p><p>In this document we'll mostly use lowercase letters, numbers, and
dashes to name things, although some other characters are allowed too,
such as <code>_&lt;&gt;!?*</code> (ex. <code>this-&gt;that</code>, <code>ready?</code>). We'll note more
examples of those cases later on as they come up.</p><h2 id="scalars">Scalars</h2><p>Clojure has support for the following kinds of scalar values:</p><pre><code class="clojure">nil
true, false
</code></pre><p><code>nil</code> is like Python's None, or Java's null. It's just another value.
Incidentally, there's no "undefined" value in Clojure --- if you try
to use a symbol which you haven't defined, then it's undefined and the
compiler will let you know about it.</p><p>As we go along, type those expressions into your REPL to see them
evaluated. These too:</p><pre><code class="clojure">1 ; integer
1N ; arbitrary-precision integer
1.2 ; float/double/decimal
1.2M ; arbitrary-precision decimal
1.2e4 ; scientific notation
1.2e4M ; sci notation of arbitrary-precision decimal
0x3a ; hex literal (58 in decimal)
1/3 ; Rational number, or "ratio".
\a ; The character "a".
"hi" ; A string.
</code></pre><p>Strings can span multiple lines --- just hit Enter and keep typing. If
you want to include a double-quote mark in a string, backslash-escape
it.</p><pre><code class="clojure">#"^foo\d?$" ; A regular expression.
:foo ; A keyword.
</code></pre><p>We'll have more to say about <a href="index.html#regular-expressions">regular
expressions</a> later on.</p><p>Keywords are just scalars that evaluate to themselves and are useful
where in other languages you might use little strings as identifiers
(for example, as the keys in a hashmap). More about keywords in the
next section (<a href="index.html#data-structures">Data Structures</a>).</p><pre><code class="clojure">'foo ; A symbol.
</code></pre><p>A <em>symbol</em> is an object that represents the <em>name</em> of something. The
single quote mark is there to keep Clojure from trying to figure out
to what the symbol refers (the quote isn't part of the identifier of
the symbol). When you want to represent the name of a thing --- rather
than the value to which it refers --- you use a symbol. Their utility
will become clearer later on when we briefly mention
<a href="index.html#macros-and-special-forms">Macros</a>.</p><blockquote><p><strong>Terminology:</strong> By "object" we just mean the internal thing that
Clojure uses to represent a value --- <em>not</em> "object" as in "object
oriented programming". Clojure is not an object oriented
language. Sure, you can easily access Java OOP objects from Clojure,
but that is outside the scope of this tutorial.</p><p>Also, the words "reference" and "refer" are used in Clojure in the
generic sense. A symbol refers to an object (it is not the object
itself). Clojure <em>also</em> happens to support something called
<em>reference types</em>. We'll cover them later on in the <a href="index.html#reference-types">Reference
Types</a> section.</p></blockquote><h2 id="data-structures">Data Structures</h2><p>Clojure comes out of the box with nice literal syntax for the various
core data structures:</p><pre><code class="clojure">[1 2 3] ; A vector (can access items by index).
[1 :two "three"] ; Put anything into them you like.
{:a 1 :b 2} ; A hashmap (or just "map", for short).
</code></pre><p>A hashmap is your typical hash/dictionary data structure. In the above
example, the keys are :a and :b, and the values are 1 and 2. One key-value
pair in a map is called an <em>entry</em>.</p><p>Although it's most common to use keywords (as shown above) for hashmap
keys, you can use any values you like for the keys as well as the
values.</p><pre><code class="clojure">#{:a :b :c} ; A set (unordered, and contains no duplicates).
'(1 2 3) ; A list (linked-list)
</code></pre><p>You generally don't use lists very often for typical sequential data
in your programs:</p><pre><code class="clojure">(def my-stuff '("shirt" "coat" "hat")) ; Works fine, but ...
(def my-stuff ["shirt" "coat" "hat"]) ; this is more typical usage.
</code></pre><p>Lists are most often used when treating code itself as just a bunch of
nested lists --- see <a href="index.html#macros-and-special-forms">Macros</a>.</p><p>BTW, don't mind that single-quote mark before the list's open paren;
it's just there to tell Clojure that this isn't a function call
(discussed in <a href="index.html#function-calls">Function Calls</a>, below), but rather, an actual
list.</p><blockquote><p>Note: In Clojure, we use the term "vector" rather than "array".
"Array" would refer to the native Java array, whereas "vector"
refers to the Clojure data structure.</p></blockquote><p>Nesting data structures works like you'd expect:</p><pre><code class="clojure">#{:a
[1 2 3]
{:foo 11 :bar 12}
#{"shirt" "coat" "hat"}}
</code></pre><p>We will see how to get at values inside nested data structures a little
later on.</p><h3 id="abstractions">Abstractions</h3><p>The data structures we just looked at (lists, vectors, maps, and sets)
are all concrete data types. The various Clojure functions for working
on them (which we will get to later on) actually aren't written to
work on the concrete types, but rather, are written to work on
abstract data types. The concrete data types are implementations of
the various abstract data types.</p><p>Some of the Clojure abstractions are:</p><ul><li>Collection (Lists, vectors, maps, and sets are all collections.)</li><li>Sequential (Lists and vectors are ordered collections.)</li><li>Associative (Hashmaps associate keys with values. Vectors associate numeric indices with values.)</li><li>Indexed (Vectors, for example, can be quickly indexed into.)</li></ul><p>In the docs for the various functions, you'll often see that they
take, for example, a "coll". This means that the particular function
will work on any of the collections.</p><blockquote><p>If you'd like to look under the covers and see what the type of
an object is, try <code>(type my-stuff)</code>.</p></blockquote><h2 id="evaluation">Evaluation</h2><p>So far you've been typing various literal values (expressions) into
the repl and Clojure has evaluated them and repeated their resulting
values back to you (printed them out in the repl):</p><pre><code class="clojure">user=&gt; "hi"
;; "hi"
user=&gt; :foo
;; :foo
user=&gt; [1 2 3]
;; [1 2 3]
</code></pre><p>Clojure evaluates the expressions you give it and tries to come up
with a resulting value. If the expression starts with an open paren,
Clojure treats it as either a macro, a <em>special form</em> (discussed
below) or else a function call.</p><h3 id="function-calls">Function Calls</h3><p>If the symbol right after the open paren names a function, Clojure
evaluates all of its function arguments first, then applies the
function to the values of those args:</p><pre><code class="clojure">(my-func arg1 arg2 arg3)
</code></pre><p>You can nest function calls as deep as tasteful discretion allows:</p><pre><code class="clojure">(my-func (my-func2 arg1
arg2)
(other-func arg-a
(foo-bar arg-x
arg-y
(+ arg-xx
arg-yy
arg-zz))
arg-b))
</code></pre><p>Note that your code will be easiest to read if you line up args to
functions vertically (as shown above). Your editor should take care of
this for you automatically.</p><p>By the way, there are no "operators" in Clojure per se; just function
names (symbols which refer to their corresponding functions). So, for
example, <code>+</code>, <code>&gt;</code>, <code>&lt;=</code>, <code>=</code>, <code>*</code>, and <code>not=</code> are all just function
names.</p><h3 id="macros-and-special-forms">Macros and Special Forms</h3><p>If an expression starts with an open paren, Clojure first checks to
see if it's a macro or special form. These are forms which don't
follow the regular evaluation rule and get special treatment from the
Clojure compiler.</p><p>Macros are like functions which take as arguments regular Clojure code
(which is, after all, just a list of expressions and (usually nested)
other lists), and returns the code transformed / expanded in some
useful way.</p><p>You write macros to add new syntax to the Clojure language, and
usually it's only done when necessary, after you've already gotten as
far as you can with plain functions.</p><p>Macros are created using <code>defmacro</code>. Writing them involves
manipulating lists (Clojure code), just like you've already
seen. Though quoting and unquoting is used to control evaluation of
the code you're handling.</p><p>Macro calls in your code get expanded at compile-time, right before
the rest of your code is compiled. Certain Clojure built-ins like
<code>let</code>, <code>def</code>, and <code>if</code> are written as special forms which are
hard-coded into the compiler rather than macros, but this is an
implementation detail; the effect is the same.</p><p>This tutorial does not discuss macros further.</p><h3 id="quoting">Quoting</h3><p>If for whatever reason you'd rather Clojure <em>not</em> treat something like
<code>(+ 1 2 3)</code> as a function call, you can "quote" it like so:</p><pre><code class="klipse-clojure nohighlight">'(+ 1 2 3)
</code></pre><p>This causes Clojure to then regard it simply as a 4-element list;
the first element of which is the symbol for some function. Reasons
for wanting to do this will become clearer later on.</p><h2 id="let-and-locals">Let and Locals</h2><p>When you want some lexically-scoped named values to use in a section
of your code, you can use the <code>let</code> expression:</p><pre><code class="klipse-clojure nohighlight">(let [width 10
height 20
thickness 2]
(println "hello from inside the `let`.")
(* width
height
thickness))
</code></pre><p>The first thing inside the <code>let</code> is a binding vector. In it, you
specify the local names you'd like to make available inside the <code>let</code>,
along with their values.</p><blockquote><p><strong>Formatting note:</strong> Your readers might appreciate you vertically
lining up the values used in the binding vector, as we've done
above with 10, 20, and 2.</p></blockquote><p>These local names are symbols that refer directly to the values you
set them to.</p><p>You can re-set the symbols in the binding vector multiple times
(building it up into the value you need), if you find it useful:</p><pre><code class="klipse-clojure nohighlight">(let [x 2
x (* x x)
x (+ x 1)]
x)
</code></pre><p>The <code>let</code> expression itself evaluates to the last expression in its
body. You can put other things inside the <code>let</code> (like our <code>println</code>
expression, in the previous example), but the overall value of the
<code>let</code> is its last expression.</p><blockquote><p>Note that the <code>println</code> expression just evaluates to nil. We don't
use its value for anything --- we only care about its <em>side-effects</em>
(printing out to the console). More about
<a href="index.html#side-effects">Side-Effects</a> shortly.</p></blockquote><h2 id="namespaces">Namespaces</h2><p>Clojure uses <em>namespaces</em> to organize function names into groups
and to keep them from colliding with other function names.
All function names live in a namespace. All the core functions
we've been using thus far are in the clojure.core namespace:</p><pre><code class="klipse-clojure nohighlight">(clojure.core/println "hi")
</code></pre><p>That's the fully-qualified name of <code>println</code>. You'd normally have to
use the fully-qualified name for functions (or else use an alias to
the namespace --- covered in a moment), but Clojure makes all the
clojure.core functions automatically available by their unqualified
names (that is, sans namespace) for convenience.</p><p>Fully-qualified names are written "namespace/symbol". The namespace
may have dots in it, which correspond to directories in your
filesystem. For example, the function foo-bar.core/my-func corresponds
to the my-func function in src/foo_bar/core.clj. (It's just a bit of
the underlying Java platform showing through that you need to use
underscores in your directory names instead of dashes).</p><p>It's most common for one source code file to correspond to one
namespace, and often comprise one <em>library</em>. At the top of your source
file, you write <code>(ns whatever)</code> and that declares the namespace for
the rest of the file.</p><p>In the repl, you can make use of libraries --- and at the same time
provide a handy alias for them --- by <em>requiring</em> them like so:</p><pre><code class="klipse-clojure nohighlight">(require '[clojure.string :as str])
</code></pre><p>Now we can use all the functions in the clojure.string library by
prefixing them with "str/". We'll do exactly this in the section below
on <a href="index.html#functions-for-working-with-strings">Functions for working with
strings</a>.</p><h2 id="functions-for-creating-data-structures">Functions for Creating Data Structures</h2><p>There are functions for creating the various data structures without
using the usual literal syntax:</p><pre><code class="clojure">(list 1 2 3) ; ⇒ '(1 2 3)
(vector 1 2 3) ; ⇒ [1 2 3]
(hash-map :a 1 :b 2) ; ⇒ {:a 1 :b 2}
(hash-set :a :b :c) ; ⇒ #{:a :b :c}
</code></pre><p>And there are various functions for converting between vectors, sets,
and maps:</p><pre><code class="clojure">(def my-vec [1 2 3])
(set my-vec) ; ⇒ #{1 2 3}
(def my-map {:a 1 :b 2})
(vec my-map) ; ⇒ [[:a 1] [:b 2]]
(flatten (vec my-map)) ; ⇒ (:a 1 :b 2)
(set my-map) ; ⇒ #{[:b 2] [:a 1]}
(def my-set #{:a :b :c :d})
(vec my-set) ; ⇒ [:a :c :b :d]
;; And for fun:
(zipmap [:a :b :c] [1 2 3]) ; ⇒ {:c 3 :b 2 :a 1}
(apply hash-map [:a 1 :b 2]) ; ⇒ {:a 1 :b 2}
</code></pre><p>(We cover <code>apply</code> in the <a href="index.html#bread-and-butter-functions">Bread and Butter
functions</a> section.)</p><p>If you need to convert to a sequential collection but don't need fast
random access to items via index, you can use <code>seq</code> instead of <code>vec</code>
(to convert to a generic linked-list-like ("sequential") data
structure). More about <code>seq</code> when we get to <a href="index.html#laziness">Laziness</a>.</p><blockquote><p>By the way, you may have noticed a pattern here: longer function
names are for passing in values one-by-one to create the data
structure, whereas the shorter function names are for passing in a
whole data structure at once:</p><pre><code>literal long name short name
------- --------- ------------------
() list *{no short name}*
[] vector vec
{} hash-map *{no short name}*
#{} hash-set set
</code></pre><p>You might think of <code>seq</code> as the short name for <code>list</code>, but that's
probably pushing it, since there are a few differences.</p></blockquote><h2 id="functions-for-working-with-data-structures">Functions For Working With Data Structures</h2><p>Getting values from data structures:</p><pre><code class="clojure">;; Vectors
(def v [:a :b :c])
(nth v 1) ; ⇒ :b
(v 1) ; ⇒ :b (same)
(first v) ; ⇒ :a
(rest v) ; ⇒ (:b :c)
(next v) ; ⇒ (:b :c)
(last v) ; ⇒ :c
;; Lists
;; Same as vectors, but can't index.
;; Maps
(def m {:a 1 :b 2})
(get m :a) ; ⇒ 1
(m :a) ; ⇒ 1 (same)
(:a m) ; ⇒ 1 (same!)
(get m :x 44) ; ⇒ 44 (if no :x, 44 is the default)
(keys m) ; ⇒ (:a :b)
(vals m) ; ⇒ (1 2)
;; Grab a key or a val from a single map entry:
(key (first m)) ; ⇒ :a
(val (first m)) ; ⇒ 1
;; Of course, note that maps are not ordered.
;; Sets
(def s #{:a :b :c})
(s :a) ; ⇒ :a
(s :z) ; ⇒ nil
</code></pre><p>Data structures in Clojure are actually <em>immutable</em> --- you can't
change them. Though it may sound batty, it actually works out nicely
in practice, and we'll read more about in the
<a href="index.html#values,-immutability,-and-persistence">Immutability</a> section
below. For now, just note that data structures can't be mutated, but
we <em>can</em> get a new modified copy of a data structure:</p><pre><code class="clojure">;; Vectors
(def v [:a :b :c])
(def li '(:a :b :c))
(conj v :d) ; ⇒ [:a :b :c :d]
(conj li :d) ; ⇒ (:d :a :b :c)
v ; ⇒ is still [:a :b :c]
li ; ⇒ is still (:a :b :c)
;; Maps
(def m {:a 1 :b 2})
(assoc m :c 3) ; ⇒ {:a 1 :c 3 :b 2}
(dissoc m :b) ; ⇒ {:a 1}
m ; ⇒ is still {:a 1 :b 2}
;; Sets
(def s #{:a :b})
(conj s :c) ; ⇒ #{:a :c :b}
(disj s :a) ; ⇒ #{:b}
s ; ⇒ is still #{:a :b}
</code></pre><p>See the <a href="http://clojure.org/cheatsheet">cheatsheet</a> for much more
you can do with these core data structures.</p><h2 id="regular-expressions">Regular Expressions</h2><p>As you've seen, Clojure provides a handy literal syntax for regular
expressions: <code>#"regex here"</code>. Clojure uses the same regular expression
syntax as Java, which is nearly the same as what Perl 5 (and Python,
and Ruby) uses. You can read more about the specifics in the Java
<a href="http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html">java.util.regex Pattern
docs</a>.</p><p>Clojure provides a number of functions for working with strings, and a
number of those can make use of regexes. See the next section for some
examples.</p><h2 id="functions-for-working-with-strings">Functions For Working With Strings</h2><p>There are a number of functions for working with strings listed in the
Strings section of the cheatsheet. Here are some examples of a few of
them:</p><pre><code class="clojure">(str "hi" "there")
;; ⇒ "hithere"
(count "hello")
;; ⇒ 5
(require '[clojure.string :as str])
;; ⇒ nil
(str/split "hello there" #" ")
;; ⇒ ["hello" "there"]
(str/join ["hello" "there"])
;; ⇒ "hellothere"
(str/join " " ["hello" "there"])
;; ⇒ "hello there"
(str/replace "hello there" "ll" "LL")
;; ⇒ "heLLo there"
</code></pre><p>Some of them make optional use of regexes. There's more in the
cheatsheet. Try them out!</p><p>Incidentally, since strings are sequential, any function that works on
sequentials works on strings. For example:</p><pre><code class="clojure">(first "hello")
;; ⇒ \h
(last "hello")
;; ⇒ \o
(rest "hello")
;; ⇒ (\e \l \l \o)
(nth "hello" 1)
;; ⇒ \e
(doseq [letter "hello"] (println letter))
;; h
;; e
;; l
;; l
;; o
;; ⇒ nil
</code></pre><p>Again, see the cheatsheet for more.</p><h2 id="values-immutability-and-persistence">Values, Immutability, and Persistence</h2><p>A <em>value</em> is fundamentally a constant thing; For example, the letter
"a" is a value. You don't "set" the letter "a" to some other value; it
always stays the letter "a". It's immutable. The value 10 is always
10. You can't ever "set 10 to 11". That makes no sense. If you want
11, you just use 11 instead of 10.</p><p>In Clojure, <em>all scalars and core data structures are like this</em>. They
are values. They are immutable. The map</p><pre><code class="clojure">{:name "John"
:hit-points 200
:super-power :resourcefulness}
</code></pre><p>is a value. If you want to "change" John's hit-points, you don't
change anything per se, but rather, you just conjure up a whole new
hashmap value.</p><p><strong>But wait:</strong> If you've done any imperative style programming in
C-like languages, this sounds crazy wasteful. <em>However</em>, the yin to
this immutability yang is that --- behind the scenes --- Clojure
shares data structures. It keeps track of all their pieces and
re-uses them pervasively. For example, if you have a 1,000,000-item
list and want to tack on one more item, you just tell Clojure, "give
me a new one but with this item added" --- and Clojure dutifully gives
you back a 1,000,001-item list in no time flat. Unbeknownst to you
it's re-using the original list.</p><p>Clojure data structures are said to be <em>persistent</em>.</p><p>And, again: this works just fine because to you the data structures
are all immutable. There is no "action at a distance". Other functions
can't change the value of a data structure you're working on because
values don't change.</p><blockquote><p>Note that, of course, Clojure doesn't do any unnecessary copying.
For example, when you pass a large data structure to a function</p><pre><code>(my-func a-really-big-data-structure)
</code></pre><p>it merely passes along a reference to the big data structure. You
can't change it in the caller's scope, because of course it's
immutable.</p><p>And of course, you don't get any action-at-a-distance in situations
like this either:</p><pre><code class="clojure">(def a [1 2 3 4 5])
(def b a)
;; Do what you will with `b`, ...
(my-func a) ; but it won't affect `a`.
</code></pre><p>since, regardless, you can't mutate the vector (neither via <code>b</code><em>nor</em> <code>a</code>).</p></blockquote><p>If you're wondering how the heck it's even possible to program at all
if you don't have "variables" and can't change anything, it will
become clear as we continue.</p><h2 id="control-structures">Control Structures</h2><p>Clojure has most of the usual control structures you'd expect to find,
for example: <code>if</code>, <code>and</code>, <code>or</code>, and <code>cond</code>. You can find them listed
in the <a href="http://clojure.org/cheatsheet">Cheatsheet</a>.</p><p>Note that they are all <em>expressions</em> in Clojure, and evaluate to
something. So, for example, this <code>if</code> expression:</p><pre><code class="clojure">(if motor-turning?
"yes"
"no")
</code></pre><p>Evaluates to either the value "yes" or the value "no".</p><p>Looping is handled by either using one of the various built-in
functions such as <code>map</code>, <code>filter</code>, <code>reduce</code>, <code>for</code>, etc., or else it's
handled by manually using <code>loop</code> and using recursion. We'll get to
these shortly.</p><p>Incidentally, looping is something that is required far less in
Clojure than in imperative languages like Python and Java. The
functions that Clojure provides often makes looping unnecessary.
For example, where in Python you might do something like this:</p><pre><code class="python">specific_stuff = []
for i in my_items:
if is_what_i_want(i):
specific_stuff.append(i)
</code></pre><p>in Clojure you lose the loop and it becomes:</p><pre><code class="clojure">(def specific-stuff (filter what-i-want? my-items))
</code></pre><p>This sort of thing comes up again and again, and we'll cover more
examples of it in the <a href="index.html#bread-and-butter-functions">Bread and Butter
functions</a> section.</p><h2 id="truthiness">Truthiness</h2><p>In <code>(if &lt;test&gt; &lt;then-this&gt; &lt;otherwise-this&gt;)</code> (and in <code>and</code>, <code>or</code>,
<code>cond</code>, etc. expressions), Clojure checks if the <code>&lt;test&gt;</code> evaluates to
something that looks either true or false. Clojure takes a very simple
approach here: <code>nil</code> and <code>false</code> are falsey; everything else is
truthy.</p><p>This means that zero, the empty string, and empty core data structures
are all true:</p><pre><code class="clojure">(if 0 :t :f) ; ⇒ :t
(if "" :t :f) ; ⇒ :t
(if [] :t :f) ; ⇒ :t
(if {} :t :f) ; ⇒ :t
(if #{} :t :f) ; ⇒ :t
</code></pre><p>If you want to check if one of those is <em>empty</em>, you could use the
<code>empty?</code> function, though, the docs recommend using this idiom:</p><pre><code class="clojure">(if (seq my-stuff)
"still has stuff left"
"all gone")
</code></pre><h2 id="equality">Equality</h2><p>You'll often check for equality using <code>=</code> (and likewise inequality
using <code>not=</code>), for example:</p><pre><code class="clojure">(if (= tries max-tries)
"you're done"
"keep going")
</code></pre><p><code>=</code> recursively checks equality of nested data structures (and
considers lists and vectors containing the same values in the same
order as equal), for example:</p><pre><code class="clojure">(= {:a [1 2 3] :b #{:x :y} :c {:foo 1 :bar 2}}
{:a '(1 2 3) :b #{:y :x} :c {:bar 2 :foo 1}})
;; ⇒ true
</code></pre><p>There's also a double-equals function <code>==</code> that is more forgiving
across various types of numbers:</p><pre><code class="clojure">(= 4 4.0)
;; ⇒ false
(== 4 4.0)
;; ⇒ true
</code></pre><p>See the docs for
<a href="http://clojuredocs.org/clojure_core/clojure.core/=">=</a> and
<a href="http://clojuredocs.org/clojure_core/clojure.core/==">==</a> for more
info.</p><h2 id="predicates-and-comparators">Predicates and Comparators</h2><p><em>Predicates</em> are functions that take one or more arguments and return
a true or false value. They usually are named with a trailing question
mark, for example, <code>even?</code>, <code>odd?</code>, <code>nil?</code>, etc. Though, some names
don't have the question mark, such as <code>&gt;</code>, <code>&gt;=</code>, <code>&lt;</code>, <code>&lt;=</code>, <code>=</code>, <code>==</code>,
and <code>not=</code>.</p><p><em>Comparators</em> are functions that take 2 args and return -1, 0, or 1
depending upon whether the first arg is less than, equal to, or
greater than the second arg. The main one is <code>compare</code>.</p><h2 id="vars">Vars</h2><p>Near the top of this tutorial is the following definition:</p><pre><code class="clojure">(def the-answer 42)
</code></pre><p>The thing being defined here (behind the scenes) is officially called
a <em>Var</em>. The symbol "<code>the-answer</code>" refers to that var which itself
refers to the value 42:</p><p>the-answer (a symbol) → a var → 42 (a value).</p><p>When Clojure sees "<code>the-answer</code>", it automatically looks up the var,
then from there finds and returns the value 42.</p><p>Recall that <a href="index.html#let-and-locals">locals</a> don't involve vars at all:
those symbols refer directly to their values.</p><h2 id="functions-defining-your-own">Functions: Defining Your Own</h2><p>You can create a function using <code>fn</code>, and give it a name using <code>def</code>:</p><pre><code class="klipse-clojure nohighlight">(def my-func
(fn [a b]
(println "adding them!")
(+ a b)))
</code></pre><p>As you might guess, this actually creates the symbol <code>my-func</code> which
refers to a var which itself refers to the function (which is a
value). Call it:</p><pre><code class="klipse-clojure nohighlight">(my-func 10 20)
</code></pre><p>But for creating top-level functions, it's more convenient to use
<code>defn</code> (which uses <code>def</code> under the hood):</p><pre><code class="clojure">(defn my-func
"Docstring goes here."
[a b]
(println "adding them!")
(+ a b))
</code></pre><p>A few points to note:</p><ul><li>The function parameters (<code>a</code> and <code>b</code>) are present in a vector
(just like with the <code>let</code> expression, except we don't include
values for them).</li><li>Inside <code>my-func</code> you can do a sequence of operations if you like
(for example, our <code>println</code> call) --- just like in a <code>let</code> --- but
the value of the last expression is what the function call as a
whole will evaluate to.</li><li>Function definitions (using <code>defn</code>) should only go at the
"top-level".</li></ul><p>Functions can return data structures instead of just scalars:</p><pre><code class="clojure">(defn foo
[x]
[x (+ x 2) (* x 2)])
</code></pre><p>and you can of course pass them data structures as well:</p><pre><code class="clojure">(defn bar
[x]
(println x))
(bar {:a 1 :b 2})
(bar [1 2 3])
</code></pre><p>To define a function to take, say, two or more arguments:</p><pre><code class="clojure">(defn baz
[a b &amp; the-rest]
(println a)
(println b)
(println the-rest))
</code></pre><p>Any additional args you pass beyond the first two get packaged into a
sequence assigned to <code>the-rest</code>. To have that function take <em>zero</em> or
more arguments, change the parameter vector to just <code>[&amp; the-rest]</code>.</p><h3 id="layout-of-functions">Layout of Functions</h3><p>Your author likes to write his functions in a top-down fashion:</p><pre><code class="clojure">;; BROKEN pseudocode
(do-it)
(defn do-it
[]
(... (my-func-a ...)))
(defn my-func-a
[...]
(... (my-func-b ...)))
(defn my-func-b ...)
</code></pre><p>but Clojure doesn't like that because it wants to have at least
<em>heard</em> about a function before you write a call to it. To let Clojure
know about a function's existence, use <code>declare</code>:</p><pre><code class="clojure">;; pseudocode
(declare do-it)
(do-it)
(declare my-func-a)
(defn do-it
[]
(... (my-func-a ...)))
(declare my-func-b)
(defn my-func-a
[...]
(... (my-func-b ...)))
(defn my-func-b ...)
</code></pre><h2 id="side-effects">Side-effects</h2><p>Some expressions in Clojure have side-effects. Many do not. All
expressions evaluate to something.</p><p>For example, <code>(+ 1 2)</code> evaluates to 3 and has no side-effects.
<code>(println "hi")</code> evaluates to nil and has the side-effect of printing
"hi" to standard out. You usually call <code>println</code> for the side-effect,
not for the return value.</p><p>Pure functions are those which have no side-effects and which do not
depend upon anything outside to compute their return value(s): you
pass it one or more values, and it returns one or more values.</p><p>If you want to make an expression that has some side-effects before
it evaluates to a value, use <code>do</code>:</p><pre><code class="clojure">(do
(println "Spinning up warp drive, captain ...")
(spin-up-warp-drive)
(get-engine-temperature))
</code></pre><p>There are a handful of functions/macros/special-forms in Clojure for
making use of side-effects, and they are spelled with a "do" at the
beginning. Try these on for size:</p><pre><code class="klipse-clojure nohighlight">(def my-items ["shirt" "coat" "hat"])
(doseq [i my-items]
(println i))
</code></pre><pre><code class="klipse-clojure nohighlight">(dotimes [i 10]
(println "counting:" i))
</code></pre><p>There's also <code>dorun</code> and <code>doall</code>, both of which are discussed below in
the section on <a href="index.html#laziness">Laziness</a>.</p><p>We say that <code>let</code> expressions and function bodies (and also <code>loop</code>
expressions, which you'll read about later in <a href="index.html#looping-and-recursion">Looping and
Recursion</a>) have an "implicit do": within them
you can list expressions one after another, and they all get evaluated
in order (presumably for the side-effects), but the last one is what
determines the overall resulting value of the <code>let</code> expression.</p><blockquote><p>Incidentally, if in the binding vector of a <code>let</code> you'd like to have
some side-effects happen and aren't really concerned about the local
values involved, it's customary to use "_" (an underscore) as the
identifier:</p><pre><code class="clojure">(let [_ (do-something)
_ (println "done with that")
x 10]
...)
</code></pre><p>There's nothing special about the identifier "_" --- it's just
shorter to type than, say, "this-is-of-no-consequence".</p></blockquote><p>There's a version of <code>if</code> which supports no "else" expression and
which provides an "implicit do": it's spelled "<code>when</code>" (and likewise
with <code>if-not</code><code>when-not</code>).</p><h2 id="destructuring">Destructuring</h2><p>Clojure provides a little bit of extra syntactic support for assigning
values to locals in <code>let</code> expressions and function definitions. Using
<code>let</code> as an example, suppose you have a nested data structure, and
you'd like to assign some values in it to locals. Where you <em>could</em> do
this:</p><pre><code class="clojure">(def games [:chess :checkers :backgammon :cards])
(let [game-a (games 0)
game-b (games 1)
game-c (games 2)
game-d (games 3)]
...
...)
</code></pre><p>Destructuring allows you to instead write:</p><pre><code class="clojure">(let [[game-a game-b game-c game-d] games]
...
...)
</code></pre><p>The thing to the left of "games" in the binding vector is referred to
as the "binding form". In the above case, the binding form is a
vector.</p><p>The way it works is: if the binding form is a vector, Clojure assumes
that the thing you're trying to assign to it must also be a vector,
and so it unpacks the values from that data structure into the
corresponding items listed in the binding form.</p><p>If you want to omit one or more of the values in the <code>games</code>, you
can do so like this:</p><pre><code class="clojure">(let [[_ my-game _ your-game] games]
...
...)
</code></pre><p>The underscore is just used as a placeholder. It's a valid identifier,
but conventionally used when you don't care what value it gets. Above,
my-game gets :checkers and your-game gets :cards.</p><p>Destructuring also works for maps in additon to vectors. For example,
instead of:</p><pre><code class="clojure">(def concert {:band "The Blues Brothers"
:location "Palace Hotel Ballroom"
:promos "Ladies night, tonight"
:perks "Free parking"})
(let [band (concert :band)
location (concert :location)
promos (concert :promos)
perks (concert :perks)]
...
...)
</code></pre><p>you <em>could</em> do:</p><pre><code class="clojure">(let [{band :band
location :location
promos :promos
perks :perks} concert]
...
...)
</code></pre><p>but an even better shortcut that destructuring provides for that is:</p><pre><code class="clojure">(let [{:keys [band location promos perks]} concert]
...
...)
</code></pre><h2 id="laziness">Laziness</h2><p>Most of the sequences Clojure creates (via calls to <code>map</code>, <code>reduce</code>,
<code>filter</code>, <code>for</code>, etc. --- covered in the next section) are <em>lazy</em>. A
lazy sequence is one that isn't <em>realized</em> (computed) all at
once. Instead, its values are only realized when you ask for them. If
you've only asked for the first 5 values of a lazy seq, then that seq
consists of 5 values plus a box that makes more values only when you
ask for them. .</p><p>A nice feature of laziness is that you can create lazy infinite
sequences but only realize (and consume memory for) the first <em>n</em> that
you actually need.</p><p>Be aware that the repl causes lazy lists to be fully realized if you
ask to see their value (which one is apt to do). After using the repl
for a while, you start to get a false sense of eagerness. <code>;)</code></p><p>If you've got some code that generates a lazy seq and you want to realize
the whole thing right then and there, you can either use</p><ul><li><code>(doall my-lazy-seq)</code> (to get the whole thing), or else</li><li><code>(dorun my-lazy-seq)</code> (to realize each value (presumably for some
side-effects you're expecting to get in the process) but then
forget it as you proceed to realize the next one).</li></ul><h2 id="bread-and-butter-functions">Bread and Butter Functions</h2><p>Given Clojure's extensive use of immutability, persistent data
structures, and laziness, one of its strong suits is functional
programming. To this author, functional programming means:</p><ul><li>treating functions just like any other regular value (for example,
passing them as args to other functions)</li><li>writing and using functions that return other functions</li><li>avoiding mutable state, preferring instead Clojure's functional
alternatives (<code>map</code>, <code>filter</code>, <code>reduce</code>, etc.) or else just
directly using recursion.</li></ul><p>Let's try out some of the power tools that Clojure comes with. In the
subsections that follow, we've left out the corresponding links to
clojuredocs for the given functions, but you'll probably want to read
the docs and see the examples there to get the full story for each.</p><h3 id="map">map</h3><p>With <code>map</code> you can apply a function to every value in a collection.
The result is a new collection. You can often use <code>map</code> instead of
manually looping over a collection. Some examples using <code>map</code>:</p><pre><code class="klipse-clojure nohighlight">(map inc [10 20 30])
</code></pre><pre><code class="klipse-clojure nohighlight">(map str [10 20 30])
</code></pre><pre><code class="klipse-clojure nohighlight">;; You can define the function to be used on-the-fly:
(map (fn [x] (str "=" x "=")) [10 20 30])
</code></pre><pre><code class="klipse-clojure nohighlight">;; And `map` knows how to apply the function you give it
;; to multiple collections in a coordinated way:
(map (fn [x y] (str x y)) [:a :b :c] [1 2 3])
</code></pre><p>When working on more than one collection at a time, <code>map</code> is smart
enough to stop when the shorter of the colls runs out of items:</p><pre><code class="klipse-clojure nohighlight">(map (fn [x y] (str x y)) [:a :b :c] [1 2 3 4 5 6 7])
</code></pre><h3 id="filter-and-remove">filter and remove</h3><p>Use <code>filter</code> with a predicate function to pare down a collection to
just the values for which <code>(the-pred the-value)</code> returns true:</p><pre><code class="klipse-clojure nohighlight">(filter odd? (range 10))
</code></pre><p>Use <code>remove</code> for the opposite effect (which amounts to <em>removing</em> the
items for which <code>(pred val)</code> returns true):</p><pre><code class="klipse-clojure nohighlight">(remove odd? (range 10))
</code></pre><p>You will often find yourself using these functions instead
of writing loops like in imperative languages.</p><h3 id="apply">apply</h3><p><code>apply</code> is for when you have a function which takes individual args,
for example, <code>max</code>, but the values you'd like to pass to it are in a
collection. <code>apply</code> "unpacks" the items in the coll:</p><pre><code class="klipse-clojure nohighlight">(max 1 5 2 8 3)
</code></pre><pre><code class="clojure">(max [1 5 2 8 3]) ;; ERROR
</code></pre><pre><code class="klipse-clojure nohighlight">(apply max [1 5 2 8 3])
</code></pre><p>A nice feature of <code>apply</code> is that you can supply extra args which
you'd like to be treated as if they were part of the collection:</p><pre><code class="klipse-clojure nohighlight">(apply max 4 55 [1 5 2 8 3])
</code></pre><h3 id="for">for</h3><p><code>for</code> is for generating collections from scratch (again, without
needing to resort to manually looping). <code>for</code> is similar to Python's
"list comprehensions". Some examples of using <code>for</code>:</p><pre><code class="klipse-clojure nohighlight">(for [i (range 10)] i)
</code></pre><pre><code class="klipse-clojure nohighlight">(for [i (range 10)] (* i i))
</code></pre><pre><code class="klipse-clojure nohighlight">(for [i (range 10) :when (odd? i)] [i (str "&lt;" i "&gt;")])
</code></pre><p>Notice we snuck a "<code>:when (odd? i)</code>" in there. <code>for</code> even supports a
<code>:let</code> modifier in there to set up your values before getting to the
body of the <code>for</code> expression.</p><h3 id="reduce">reduce</h3><p><code>reduce</code> is a gem. You use it to apply a function to the first and
second items in a coll and get a result. Then you apply it to the
result you just got and the 3rd item in the coll. Then the result of
<em>that</em> and the 4th. And so on. The process looks something like this:</p><pre><code class="clojure">(reduce + [1 2 3 4 5])
;; → 1 + 2 [3 4 5]
;; → 3 [3 4 5]
;; → 3 + 3 [4 5]
;; → 6 [4 5]
;; → 6 + 4 [5]
;; → 10 [5]
;; → 10 + 5
;; =&gt; 5
</code></pre><p>And, of course, you can supply your own function if you like:</p><pre><code class="clojure">(reduce (fn [x y] ...) [...])
</code></pre><p>A nice additional feature of <code>reduce</code> is that you can supply a value
for it to start off with:</p><pre><code class="klipse-clojure nohighlight">(reduce + 10 [1 2 3 4 5])
</code></pre><p>This by itself is pretty handy. But it gets even better. Since you can
supply an initial argument, and you can supply your own function, you
can use a <em>data structure</em> as that initial argument and have your
function "build it up" as you go. For example:</p><pre><code class="clojure">(reduce (fn [accum x]
(assoc accum
(keyword x)
(str x \- (rand-int 100))))
{}
["hi" "hello" "bye"])
;; → {}
;; → {:hi "hi-29"}
;; → {:hi "hi-29" :hello "hello-42"}
;; ⇒ {:hi "hi-29" :hello "hello-42" :bye "bye-10"}
</code></pre><p>Building up some accumulator using <code>reduce</code> and your own custom
function is a fairly common pattern (and once again allows us to
avoid looping and manipulations of anything mutable).</p><h3 id="partial-comp-and-iterate">partial, comp, and iterate</h3><p>With <code>partial</code> you can create a function which wraps another one and
passes it some standard arguments every time, along with the ones you
supply right when you call it. For example:</p><pre><code class="klipse-clojure nohighlight">(defn lots-of-args [a b c d] (str/join "-" [a b c d]))
</code></pre><pre><code class="klipse-clojure nohighlight">(lots-of-args 10 20 30 40)
</code></pre><pre><code class="klipse-clojure nohighlight">(def fewer-args (partial lots-of-args 10 20 30))
</code></pre><pre><code class="klipse-clojure nohighlight">(fewer-args 40)
</code></pre><pre><code class="klipse-clojure nohighlight">(fewer-args 99)
</code></pre><p><code>comp</code> is for composing a function from other ones. That is, <code>(comp foo bar baz)</code> gives you a function that will first call baz on
whatever you pass it, then bar on the result of that, then foo on the
result of <em>that</em>, and finally returns the result. Here's a silly
example:</p><pre><code class="klipse-clojure nohighlight">(defn wrap-in-stars [s] (str "*" s "*"))
</code></pre><pre><code class="klipse-clojure nohighlight">(defn wrap-in-equals [s] (str "=" s "="))
</code></pre><pre><code class="klipse-clojure nohighlight">(defn wrap-in-ats [s] (str "@" s "@"))
</code></pre><pre><code class="klipse-clojure nohighlight">(def wrap-it (comp wrap-in-ats
wrap-in-equals
wrap-in-stars))
</code></pre><pre><code class="klipse-clojure nohighlight">(wrap-it "hi")
</code></pre><pre><code class="klipse-clojure nohighlight">;; Which is the same as:
(wrap-in-ats (wrap-in-equals (wrap-in-stars "hi")))
</code></pre><p><code>(iterate foo x)</code> yields an infinite lazy list consisting
of:</p><pre><code class="clojure">(x
(foo x)
(foo (foo x))
(foo (foo (foo x)))
...)
</code></pre><p>To just take the first, say, 5 values from an infinite list, try this:</p><pre><code class="klipse-clojure nohighlight">(defn square [x] (* x x))
</code></pre><pre><code class="klipse-clojure nohighlight">(take 5 (iterate square 2))
</code></pre><h2 id="looping-and-recursion">Looping and Recursion</h2><p>As you've seen in the previous section, looping is often just handled
by various built-in functions such as <code>map</code>, <code>filter</code>, and <code>reduce</code>.
You should use those whenever you can. For times when you need more
manual control, you can write loops yourself. By-hand.</p><p>A <code>loop</code> expression looks like a <code>let</code>; you set up locals in its
binding vector, then the body of the loop is executed. The body has an
implicit do, just like <code>let</code> and function bodies. However, within the
body of the <code>loop</code> expression you exit at some point with what you
have or else loop again. When you loop again, you call the loop (using
<code>recur</code>) as if it's a function, passing new values in for the ones you
previously set up in the binding vector. The loop calling itself like
this is called <em>recursion</em>. Here's a trivial example:</p><pre><code class="klipse-clojure nohighlight">(loop [accum []
i 1]
(if (= i 10)
accum
(recur (conj accum i)
(inc i))))
</code></pre><p>The state in this loop is carried in the <code>accum</code> vector, which we
update each time through the loop. <code>i</code> is the counter, and we finally
exit the loop (which evaluates to <code>accum</code>) when i equals 10.</p><p><code>accum</code> could be any other data structure, and that call <code>(conj accum i)</code> could be any expression that yields a new data structure to take
the old one's place the next time through.</p><p>You don't actually need a <code>loop</code> to use <code>recur</code>. If you use <code>recur</code> in
a function body, it will just call the function again, replacing the
args it was previously called with with the ones you pass to <code>recur</code>.</p><p>Finally, recall that if you just need looping for the side-effects
only, see <code>doseq</code> and <code>dotimes</code>.</p><h2 id="reference-types">Reference Types</h2><p>Although we've been saying all along that Clojure doesn't have
"variables", and that everything is immutable, ... that's not entirely
true.</p><p>For when you really do need mutability, Clojure offers <em>reference
types</em>. And Clojure provides built-in support for helping you mutate
them in safe ways.</p><p>Aside from vars (which is a sort of special reference type), there are
3 kinds of reference types:</p><ul><li>Atoms</li><li>Refs</li><li>Agents</li></ul><p>You might typically create a reference type like this:</p><pre><code class="clojure">(def my-atom (atom {}))
</code></pre><p>This reference type is an atom, and its state is a hashmap (an empty
one, for now). Here, the <code>my-atom</code> symbol refers to a var which refers
to the atom.</p><p>Although you <em>still</em> can't literally change the value of the atom, you
<em>can</em> swap in a new hashmap value for it any time you like. To retrieve
the value of the atom, you "deref" it, or just use the shorter "@"
syntax. Here's an (atom-specific) example:</p><pre><code class="klipse-clojure nohighlight">(def my-atom (atom {:foo 1}))
</code></pre><pre><code class="klipse-clojure nohighlight">@my-atom
</code></pre><pre><code class="klipse-clojure nohighlight">(swap! my-atom update-in [:foo] inc)
</code></pre><pre><code class="klipse-clojure nohighlight">@my-atom
</code></pre><p>... and we've just changed the state of the atom. (Note, <code>swap!</code> is a
function used only for atoms. There are other specific functions for
working with the other reference types.)</p><p>The point of having reference types is that, in your programs, you may
want to represent an <em>identity</em>. An identity is something that may
change its state over time, but is still the same entity,
regardless. In Clojure, an identity is represented by a reference
type, and its state is represented by a value.</p><p>We won't discuss reference types further in this tutorial. Perhaps
someone will write a good topical guide...</p><h2 id="see-also">See Also</h2><ul><li><a href="https://www.4clojure.com/">4Clojure</a> --- try out what you've
learned so far by interactively solving a set of interesting
programming problems.</li></ul><h2 id="not-covered-in-this-tutorial">Not Covered In This Tutorial</h2><p>To keep this tutorial down to a manageable length, advanced topics or
other far (or not so far) corners not covered herein include but
aren't limited to: function literals, multiple-arity functions,
exceptions, dynamic scoping of vars, namespaced keywords, metadata,
any substantial coverage of macros, transients, zippers, delays,
futures, promises, refs, agents or anything about multithreading,
thread-first, thread-last, trampolines, datatypes, protocols,
multimethods, and Java interop.</p><h2 id="contributors">Contributors</h2><p>John Gabriele <a href="mailto:jmg3000@gmail.com">jmg3000@gmail.com</a> (original author)</p>
<div id="prev-next">
<a href="../getting_started/index.html">&laquo; Getting Started with Clojure</a>
||
<a href="../emacs/index.html">Clojure with Emacs &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="index.html">Introduction to Clojure</a></li>
<li><a href="../emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="../parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="../growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
<link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">
<script>
window.klipse_settings = {
"selector" : ".klipse-clojure"
};
</script>
<script src="https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"></script>
</body>
</html>

View file

@ -0,0 +1,486 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides: Parsing XML in Clojure</title>
<meta name="description" content="This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.What Version of Clojure Does This Guide Cover?">
<meta property="og:description" content="This work is licensed under a Creative Commons
Attribution 3.0 Unported License (including images &amp;
stylesheets). The source is available on
Github.What Version of Clojure Does This Guide Cover?">
<meta property="og:url" content="https://clojure-doc.github.io/articles/tutorials/parsing_xml_with_zippers/" />
<meta property="og:title" content="Parsing XML in Clojure" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/tutorials/parsing_xml_with_zippers/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ><a href="../../../index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="custom-page">
<div id="page-header">
<h2>Parsing XML in Clojure</h2>
</div>
<p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images &amp;
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
Github</a>.</p><h2 id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.4 and Leiningen 2.x.</p><h2 id="overview">Overview</h2><p>Try as you might, XML is difficult to avoid. This is particularly true
in the Java ecosystem. This guide will show you how to parse XML with
the minimum amount of pain using the excellent tools available in
Clojure.</p><h2 id="parsing-nzb-files">Parsing NZB files</h2><p>For the purpose of the tutorial I have chosen a simple and fairly well
known XML file format: NZB. An NZB file is used to describe files to
download from NNTP servers. In this tutorial we will take a basic NZB
document and turn it into a Clojure map.</p><p>Let us start by creating a new project (for details on using
Leiningen, see <a href="https://clojure-doc.org/articles/tutorials/leiningen/">this guide</a>:</p><pre><code class="bash">$ lein new nzb
</code></pre><p>Now edit <code>project.clj</code> to contain the following:</p><pre><code class="clojure">(defproject nzb "0.1.0-SNAPSHOT"
:description ""
:url ""
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.4.0"]
[org.clojure/data.zip "0.1.1"]])
</code></pre><p>We are including a dependency on
<a href="https://github.com/clojure/data.zip">clojure.data.zip</a>, which is a
"system for filtering trees, and XML trees in particular".</p><p>Make a dir called <code>dev-resources</code> at the root of your project, and
create a file named <code>example.nzb</code> inside of it. This will be the file
we use to test our code (taken from
<a href="http://en.wikipedia.org/wiki/NZB">wikipedia</a>). <code>dev-resources</code> is by
convention the location to store file resources you use during
development / testing.</p><p>Put the following XML in the example.nzb file:</p><pre><code class="xml">&lt;?xml version="1.0" encoding="iso-8859-1" ?&gt;
&lt;!-- &lt;!DOCTYPE nzb PUBLIC "-//newzBin//DTD NZB 1.1//EN" "http://www.newzbin.com/DTD/nzb/nzb-1.1.dtd"&gt; --&gt;
&lt;nzb xmlns="http://www.newzbin.com/DTD/2003/nzb"&gt;
&lt;head&gt;
&lt;meta type="title"&gt;Your File!&lt;/meta&gt;
&lt;meta type="tag"&gt;Example&lt;/meta&gt;
&lt;/head&gt;
&lt;file poster="Joe Bloggs &amp;lt;bloggs@nowhere.example&amp;gt;" date="1071674882" subject="Here's your file! abc-mr2a.r01 (1/2)"&gt;
&lt;groups&gt;
&lt;group&gt;alt.binaries.newzbin&lt;/group&gt;
&lt;group&gt;alt.binaries.mojo&lt;/group&gt;
&lt;/groups&gt;
&lt;segments&gt;
&lt;segment bytes="102394" number="1"&gt;123456789abcdef@news.newzbin.com&lt;/segment&gt;
&lt;segment bytes="4501" number="2"&gt;987654321fedbca@news.newzbin.com&lt;/segment&gt;
&lt;/segments&gt;
&lt;/file&gt;
&lt;/nzb&gt;
</code></pre><p><em><em>Note</em> The eagle eyed among you will notice that I have commented out the
DOCTYPE declaration, as this causes an Exception to be thrown. I will
show you how to get around this towards the end of the tutorial.</em></p><p>Let's write a high level test to illustrate more clearly what we are
trying to do. Open up the <code>test/nzb/core_test.clj</code> file and make enter
the following:</p><pre><code class="clojure">(ns nzb.core-test
(:use clojure.test
nzb.core)
(:require [clojure.java.io :as io]))
(deftest test-nzb-&gt;map
(let [input (io/resource "example.nzb")]
(is (= {:meta {:title "Your File!"
:tag "Example"}
:files [{:poster "Joe Bloggs &lt;bloggs@nowhere.example&gt;"
:date 1071674882
:subject "Here's your file! abc-mr2a.r01 (1/2)"
:groups ["alt.binaries.newzbin"
"alt.binaries.mojo"]
:segments [{:bytes 102394
:number 1
:id "123456789abcdef@news.newzbin.com"}
{:bytes 4501
:number 2
:id "987654321fedbca@news.newzbin.com"}]}]}
(nzb-&gt;map input)))))
</code></pre><p>This should be fairly self-explanatory, I have directly translated the
XML into Clojure data structures of maps and vectors. If we were to
just use the <code>clojure.xml</code> library to parse the NZB file, we get a
tree based representation. For example:</p><pre><code class="clojure">(-&gt; "example.nzb" io/resource io/file xml/parse)
{:tag :nzb,
:attrs {:xmlns "http://www.newzbin.com/DTD/2003/nzb"},
:content
[{:tag :head,
:attrs nil,
:content
[{:tag :meta, :attrs {:type "title"}, :content ["Your File!"]}
{:tag :meta, :attrs {:type "tag"}, :content ["Example"]}]}
{:tag :file,
:attrs
{:poster "Joe Bloggs &lt;bloggs@nowhere.example&gt;",
:date "1071674882",
:subject "Here's your file! abc-mr2a.r01 (1/2)"},
:content
[{:tag :groups,
:attrs nil,
:content
[{:tag :group, :attrs nil, :content ["alt.binaries.newzbin"]}
{:tag :group, :attrs nil, :content ["alt.binaries.mojo"]}]}
{:tag :segments,
:attrs nil,
:content
[{:tag :segment,
:attrs {:bytes "102394", :number "1"},
:content ["123456789abcdef@news.newzbin.com"]}
{:tag :segment,
:attrs {:bytes "4501", :number "2"},
:content ["987654321fedbca@news.newzbin.com"]}]}]}]}
</code></pre><p>That's great, and can sometimes be enough. But I would rather work
with the representation I have in the test. To do that, we need a way
of traversing this tree and picking out the pieces of information we
require. The <code>clojure.zip</code> and <code>clojure.data.zip</code> libraries are
perfect for this. The
<a href="http://clojure.github.com/data.zip/">documentation</a> for the
<code>data.zip</code> library on github is nice, but it initially left me a
little confused as to how to go about using the library (not being
familiar with zippers).</p><h3 id="a-simple-example">A Simple Example</h3><p>Zippers allow you to easily traverse a data structure. Let's play with
it in a REPL and start with the root node of our NZB file:</p><pre><code class="clojure">(require '[clojure.java.io :as io])
(require '[clojure.xml :as xml])
(require '[clojure.zip :as zip])
(require '[clojure.data.zip.xml :as zip-xml])
(def root (-&gt; "example.nzb" io/resource io/file xml/parse zip/xml-zip))
</code></pre><p>Now we have a zipper for the root element of our document, we can
start traversing it for information. The two main functions we will
use for this are <code>xml-&gt;</code> and <code>xml1-&gt;</code>. The former returns a sequence
of items based on the predicates given to it, the latter returning the
first matching item. As an example, let's get the meta data from the NZB
document <code>root</code> and create a Clojure map:</p><pre><code class="clojure">(into {}
(for [m (zip-xml/xml-&gt; root :head :meta)]
[(keyword (zip-xml/attr m :type))
(zip-xml/text m)]))
;; =&gt; {:title "Your File!", :tag "Example"}
</code></pre><p>A couple of things are happening here. First of all we use <code>xml-&gt;</code> to
return a sequence of <code>&lt;meta&gt;</code> tags that live under the <code>&lt;head&gt;</code> tag:</p><pre><code class="clojure">(zip-xml/xml-&gt; root :head :meta)
</code></pre><p>We use the <code>for</code> list comprehension macro to evaluate each item in the
sequence. For each item we find the contents of the <code>:type</code> attribute
using the <code>attr</code> function:</p><pre><code class="clojure">(keyword (zip-xml/attr m :type))
</code></pre><p>This returns us the contents of the attribute as a string, which we
turn into a <code>keyword</code> to use as the key in the map. We then use the
<code>text</code> function to get the textual contents of the meta tag:</p><pre><code class="clojure">(zip-xml/text m)
</code></pre><p>We make a tuple of these values, and pass the resulting sequence to
<code>into</code> to build the map.</p><h2 id="putting-it-together">Putting It Together</h2><p>Using only these functions, we can parse the raw XML into the Clojure
data structure from our unit test. If you like, open
<code>./src/nzb/core.clj</code>, and make the changes as you read along.</p><p>First let's define our <code>nzb-&gt;map</code> function from the test, and pull in
the code we have already written for parsing the metadata of the NZB:</p><pre><code class="clojure">(ns nzb.core
(:require [clojure.xml :as xml]
[clojure.java.io :as io]
[clojure.zip :as zip]
[clojure.data.zip.xml :as zip-xml]))
(defn meta-&gt;map
[root]
(into {}
(for [m (zip-xml/xml-&gt; root :head :meta)]
[(keyword (zip-xml/attr m :type))
(zip-xml/text m)])))
(defn file-&gt;map
[file]
;; TODO
)
(defn nzb-&gt;map
[input]
(let [root (-&gt; input
io/input-stream
xml/parse
zip/xml-zip)]
{:meta (meta-&gt;map root)
:files (mapv file-&gt;map (zip-xml/xml-&gt; root :file))}))
</code></pre><p>The only new thing here is the use of <code>io/input-stream</code> to allow us to
use anything as <code>input</code> that the <code>io/input-stream</code> supports. These are
currently <code>OutputStream</code>, <code>File</code>, <code>URI</code>, <code>URL</code>, <code>Socket</code>, <code>byte array</code>, and <code>String</code> arguments. See the
<a href="http://clojure.github.com/clojure/clojure.java.io-api.html">clojure.java.io</a>
docs for details.</p><p>Now let's fill in the <code>file-&gt;map</code> function:</p><pre><code class="clojure">(defn segment-&gt;map
[seg]
{:bytes (Long/valueOf (zip-xml/attr seg :bytes))
:number (Integer/valueOf (zip-xml/attr seg :number))
:id (zip-xml/xml1-&gt; seg zip-xml/text)})
(defn file-&gt;map
[file]
{:poster (zip-xml/attr file :poster)
:date (Long/valueOf (zip-xml/attr file :date))
:subject (zip-xml/attr file :subject)
:groups (vec (zip-xml/xml-&gt; file :groups :group zip-xml/text))
:segments (mapv segment-&gt;map
(zip-xml/xml-&gt; file :segments :segment))})
</code></pre><p>Again, nothing new. We simply pick out the pieces of the document we
wish to process using a combination of the <code>xml1-&gt;</code>, <code>xml-&gt;</code>, <code>attr</code>,
and <code>text</code> functions. Run the test, and it should pass.</p><h3 id="prevent-parsing-the-dtd">Prevent Parsing the DTD</h3><p>Interestingly, if we uncomment the DTD declaration in the
<code>example.nzb</code> file, our code now explodes with an Exception:</p><pre><code>org.xml.sax.SAXParseException: The markup declarations contained or pointed to by the document type declaration must be well-formed
</code></pre><p>We can fix this by swapping out the <code>SAXParserFactory</code> and setting a
feature to not validate the DTD. Here's how:</p><p>Update the <code>ns</code> declaration to include some required classes:</p><pre><code class="clojure">(ns nzb.core
(:require [clojure.xml :as xml]
[clojure.java.io :as io]
[clojure.zip :as zip]
[clojure.data.zip.xml :as zip-xml])
(:import (javax.xml.parsers SAXParser SAXParserFactory)))
</code></pre><p>Define a function to switch out the SAXParserFactory:</p><pre><code class="clojure">(defn startparse-sax
"Don't validate the DTDs, they are usually messed up."
[s ch]
(let [factory (SAXParserFactory/newInstance)]
(.setFeature factory "http://apache.org/xml/features/nonvalidating/load-external-dtd" false)
(let [^SAXParser parser (.newSAXParser factory)]
(.parse parser s ch))))
</code></pre><p>Update our nzb-&gt;map definition to use it:</p><pre><code class="clojure">(defn nzb-&gt;map
[input]
(let [root (-&gt; input
io/input-stream
(xml/parse startparse-sax)
zip/xml-zip)]
{:meta (meta-&gt;map root)
:files (mapv file-&gt;map (zip-xml/xml-&gt; root :file))}))
</code></pre><p>Yay, our test passes again.</p><h2 id="query-predicates">Query Predicates</h2><p>There are a few other useful functions in the <code>clojure.data.zip.xml</code>
ns we haven't yet looked at, namely: <code>text=</code>, <code>attr=</code>, and <code>tag=</code>.
These functions allow you to construct query predicates to run against
a given node. As an example, let's pull out the first file segment
from the <code>example.nzb</code> file using the <code>attr=</code> function:</p><pre><code class="clojure">(zip-xml/xml1-&gt; root
:file
:segments
:segment
(zip-xml/attr= :number "1"))
zip-xml/text)
"123456789abcdef@news.newzbin.com"
</code></pre><p>From the root node of the document we reach down into <code>:file</code>,
<code>:segments</code>, and <code>:segment</code> in turn, then use the <code>attr=</code> query
predicate to match a <code>:segment</code> with a value of <code>"1"</code>.</p><p>Interestingly enough, the other two query predicates have shortcuts
for their use. You have already been using the <code>tag=</code> query predicate
every time you use a keyword to locate a tag. To use the <code>text=</code>
predicate easily, just use a string. For example, to retrieve the
second <code>:segment</code> based on its content of
<code>987654321fedbca@news.newzbin.com</code>:</p><pre><code class="clojure">(zip-xml/xml1-&gt; root
:file
:segments
:segment
"987654321fedbca@news.newzbin.com")
;; ... the resulting node
</code></pre><p>Finally, you can combine these query predicates to match multiple
things on a given node by using a vector:</p><pre><code class="clojure">(zip-xml/xml1-&gt; root
:file
:segments
:segment
[(zip-xml/attr= :number "1")
(zip-xml/attr= :bytes "102394")]
zip-xml/text)
"123456789abcdef@news.newzbin.com"
</code></pre><p>Here we are matching on both the <code>:number</code> attribute being <code>"1"</code>, and
the <code>:bytes</code> attribute being <code>"102394"</code>. Obviously, you can use
strings here to match against content too.</p><h2 id="creating-new-predicates">Creating New Predicates</h2><p>OK, now let's suppose we want to use some kind of numerical comparison
in our XML (like we might do with XPath). As it stands, we have no way
to do that with the built-in functions but we can easily define our
own.</p><p>Let's start with a general function for comparing attribute values:</p><pre><code class="clojure">(defn attr-fn
[attrname f test-val &amp; [conv-fn]]
(fn [loc]
(let [conv-fn (or conv-fn identity)
val (conv-fn (zip-xml/attr loc attrname))]
(f val test-val))))
</code></pre><p>This function takes an attribute name (<code>attrname</code>), a function for
making a comparison (<code>f</code>), a value to test agains (<code>test-val</code>) and
optionally a conversion function. Imagine our <code>example.nzb</code> file had
100 segments, and we only wanted to get segments over 75. We could now
achieve this using our general function:</p><pre><code class="clojure">(zip-xml/xml-&gt; root
:file
:segments
:segment
(attr-fn :number &gt; 75 #(Long/valueOf %))
zip-xml/text)
</code></pre><p>Let's provide a helper for this to make the syntax clearer:</p><pre><code class="clojure">(defn attr&gt;
[attrname val]
(attr-fn attrname &gt; val #(Long/valueOf %)))
(zip-xml/xml-&gt; doc
:file
:segments
:segment
(attr&gt; :number 75)
zip-xml/text)
</code></pre><p>We could build a whole suite of helper functions for examining XML
nodes, if we are unlucky enough to be required to do so :)</p><h2 id="conclusion">Conclusion</h2><p>I hope these simple examples have given you an idea of the ease with
which you can process XML using Clojure, and how simple it is to
extend the tools already provded in interesting directions.</p><h2 id="contributors">Contributors</h2><p><a href="http://blog.gaz-jones.com">Gareth Jones</a>, 2012 (original author)</p>
<div id="prev-next">
<a href="../basic_web_development/index.html">&laquo; Basic Web Development</a>
||
<a href="../growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure &raquo;</a>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="../../about/index.html">About</a></li>
<li><a href="../../content/index.html">Table of Contents</a></li>
<li><a href="../getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="../introduction/index.html">Introduction to Clojure</a></li>
<li><a href="../emacs/index.html">Clojure with Emacs</a></li>
<li><a href="../vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="../eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="../basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="index.html">Parsing XML in Clojure</a></li>
<li><a href="../growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="../../ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="../../ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="../../ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="../../ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="../../ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="../../ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="../../ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="../../ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="../../ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="../../ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="../../ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="../../ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="../../ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="../../ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="../../ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="../../ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="../../ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="../../ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="../../ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="../../ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="../../ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="../../ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="../../ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="../../ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="../../ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="../../ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="../../ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,168 @@
h1, h2, h3, h4, h5, h6 {
font-family: 'Alegreya';
}
body {
color: #333;
background-color: #f2f2f2;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 16px;
}
.container {
max-width: 1000px;
}
.right {
float: right;
text-align: right;
}
.navbar {
border-radius: 0;
box-shadow: 0 0 0 0,0 6px 12px rgba(34,34,34,0.3);
}
.navbar-default {
background-color: #428bca;
border: none;
}
.navbar-default .navbar-brand {
color: #fff;
font-family: 'Alegreya';
}
.navbar-default .navbar-brand:hover {
color: #fff;
}
.navbar-default .navbar-nav li a {
color: #fff;
}
.navbar-default .navbar-nav li a:hover {
color: #fff;
background-color: #3d80ba;
}
.navbar-default .navbar-nav .active a {
color: #fff;
background-color: #3d80ba;
}
.navbar-default .navbar-toggle:hover{
background-color: #3d80ba;
}
.navbar-default .navbar-toggle .icon-bar {
background-color: #fff;
}
#sidebar {
margin-left: 15px;
margin-top: 50px;
}
#content {
background-color: #fff;
border-radius: 3px;
box-shadow: 0 0 0 0,0 6px 12px rgba(34,34,34,0.1);
}
#content img {
max-width: 100%;
height: auto;
}
footer {
font-size: 14px;
text-align: center;
padding-top: 75px;
padding-bottom: 30px;
}
blockquote footer {
text-align: left;
padding-top: 0px;
padding-bottom: 0px;
}
#post-tags {
margin-top: 30px;
}
#prev-next {
padding: 15px 0;
}
.post-header {
margin-bottom: 20px;
}
.post-header h2 {
font-size: 32px;
}
#post-meta {
font-size: 14px;
color: rgba(0,0,0,0.4)
}
#page-header {
border-bottom: 1px solid #dbdbdb;
margin-bottom: 20px;
}
#page-header h2 {
font-size: 32px;
}
pre {
overflow-x: auto;
}
pre code {
display: block;
padding: 0.5em;
overflow-wrap: normal;
white-space: pre;
}
code {
color: #428bca;
}
pre, code, .hljs {
background-color: #f7f9fd;
}
@media (min-width: 768px) {
.navbar {
min-height: 70px;
}
.navbar-nav>li>a {
padding: 30px 20px;
}
.navbar-default .navbar-brand {
font-size: 36px;
padding: 25px 15px;
}
#content{
margin-top: 30px;
padding: 30px 40px;
}
}
@media (max-width: 767px) {
body{
font-size: 14px;
}
.navbar-default .navbar-brand {
font-size: 30px;
}
#content{
padding: 15px;
}
#post-meta .right {
float:left;
text-align: left;
}
}

View file

@ -0,0 +1,237 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8"/>
<title>Clojure Guides</title>
<meta name="description" content="Clojure Documentation">
<meta name="keywords" content="">
<link rel="canonical" href="https://clojure-doc.github.io/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
<link href="css/screen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">Clojure Guides</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li class="active" ><a href="index.html">Home</a></li>
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div id="content">
<div id="post">
<div>
<div class="jumbotron">
<div class="container">
<h1>Clojure Documentation</h1>
<p>Welcome to the community-driven documentation site for the Clojure programming language.</p>
<a class='btn btn-primary btn-lg' href='articles/tutorials/getting_started/index.html'>Get Started! »</a>
<a class="btn btn-lg" href="articles/content/index.html">See all content »</a>
<a class='btn btn-lg' href='https://github.com/clojure-doc/clojure-doc.github.io'>Contribute »</a>
</div>
</div>
<div class='row'>
<div class='col-md-4'>
<h2><a href='articles/content/index.html#essentials'>Essentials</a></h2>
<p>Tutorials aimed at new users.</p>
</div>
<div class='col-md-4'>
<h2><a href='articles/content/index.html#language-guides'>Language Guides</a></h2>
<p>Comprehensive guides on every aspect of the core language.</p>
</div>
<div class='col-md-4'>
<h2>Contributor-friendly</h2>
<p>
This material is not covered by the Clojure Contributor Agreement and is developed using <a href="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">pull-requests on GitHub</a>.
</p>
</div>
</div>
<div class='row'>
<div class='col-md-4'>
<h2><a href='articles/content/index.html#the-clojure-ecosystem'>Ecosystem & Tools</a></h2>
<p>Guides covering areas outside of the core language.</p>
</div>
<div class='col-md-4'>
<h2><a href='articles/content/index.html#tutorials-and-cookbooks'>Tutorials and Cookbooks</a></h2>
<p>Subject-specific tutorials and guides.</p>
</div>
<div class='col-md-4'>
<h2>Interactive Examples</h2>
<p><a href="https://github.com/viebel/klipse">Klipse</a> is used in several sections to provide
live, interactive code examples that you can edit to explore the concepts being
discussed.
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div id="sidebar">
<h3>Links</h3>
<ul id="links">
<li><a href="articles/about/index.html">About</a></li>
<li><a href="articles/content/index.html">Table of Contents</a></li>
<li><a href="articles/tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
<li><a href="articles/tutorials/introduction/index.html">Introduction to Clojure</a></li>
<li><a href="articles/tutorials/emacs/index.html">Clojure with Emacs</a></li>
<li><a href="articles/tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
<li><a href="articles/tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
<li><a href="articles/tutorials/basic_web_development/index.html">Basic Web Development</a></li>
<li><a href="articles/tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
<li><a href="articles/tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
<li><a href="articles/language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
<li><a href="articles/language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
<li><a href="articles/language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
<li><a href="articles/language/functions/index.html">Functions in Clojure</a></li>
<li><a href="articles/language/laziness/index.html">Laziness in Clojure</a></li>
<li><a href="articles/language/interop/index.html">Clojure interoperability with Java</a></li>
<li><a href="articles/language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
<li><a href="articles/language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
<li><a href="articles/language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
<li><a href="articles/language/glossary/index.html">Clojure Terminology Guide</a></li>
<li><a href="articles/ecosystem/libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
<li><a href="articles/ecosystem/libraries_authoring/index.html">Library Development and Distribution</a></li>
<li><a href="articles/ecosystem/generating_documentation/index.html">Generating Documentation</a></li>
<li><a href="articles/ecosystem/data_processing/index.html">Data Processing (Help Wanted)</a></li>
<li><a href="articles/ecosystem/web_development/index.html">Web Development (Overview)</a></li>
<li><a href="articles/ecosystem/maven/index.html">How to use Maven to build Clojure projects</a></li>
<li><a href="articles/ecosystem/community/index.html">Clojure Community</a></li>
<li><a href="articles/ecosystem/user_groups/index.html">Clojure User Groups</a></li>
<li><a href="articles/ecosystem/running_cljug/index.html">Running a Clojure User Group</a></li>
<li><a href="articles/ecosystem/books/index.html">Books about Clojure and ClojureScript</a></li>
<li><a href="articles/cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
<li><a href="articles/cookbooks/strings/index.html">Strings</a></li>
<li><a href="articles/cookbooks/math/index.html">Mathematics with Clojure</a></li>
<li><a href="articles/cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
<li><a href="articles/cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
<li><a href="articles/cookbooks/middleware/index.html">Middleware in Clojure</a></li>
<li><a href="articles/ecosystem/java_jdbc/home.html">java.jdbc - Getting Started</a></li>
<li><a href="articles/ecosystem/java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
<li><a href="articles/ecosystem/java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
<li><a href="articles/ecosystem/java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
<li><a href="articles/ecosystem/core_typed/home/index.html">core.typed - User Documentation Home</a></li>
<li><a href="articles/ecosystem/core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
<li><a href="articles/ecosystem/core_typed/rationale/index.html">core.typed - Rationale</a></li>
<li><a href="articles/ecosystem/core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
<li><a href="articles/ecosystem/core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
<li><a href="articles/ecosystem/core_typed/types/index.html">core.typed - Types</a></li>
<li><a href="articles/ecosystem/core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
<li><a href="articles/ecosystem/core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
<li><a href="articles/ecosystem/core_typed/filters/index.html">core.typed - Filters</a></li>
<li><a href="articles/ecosystem/core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
<li><a href="articles/ecosystem/core_typed/loops/index.html">core.typed - Looping constructs</a></li>
<li><a href="articles/ecosystem/core_typed/function_types/index.html">core.typed - Functions</a></li>
<li><a href="articles/ecosystem/core_typed/limitations/index.html">core.typed - Limitations</a></li>
</ul>
</div>
</div>
</div>
<footer>Copyright &copy; 2021 Multiple Authors
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="js/highlight.pack.js" type="application/javascript"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -90,6 +90,7 @@ var link_dirs = [
["bs", "../bs"],
["bug-report", "../bug-report"],
["buid", "../buid"],
["bv", "../bv"],
["bzip2", "../bzip2"],
["c", "../c"],
["c-defs", "../c-defs"],
@ -153,6 +154,7 @@ var link_dirs = [
["cpu-affinity", "../cpu-affinity"],
["cpuinfo", "../cpuinfo"],
["crc32c", "../crc32c"],
["crontab-manual", "../crontab-manual"],
["crypto", "../crypto"],
["cs135-drtools", "../cs135-drtools"],
["cs2500f16-jsonlab", "../cs2500f16-jsonlab"],
@ -256,6 +258,7 @@ var link_dirs = [
["ebml", "../ebml"],
["ebuild", "../ebuild"],
["ec", "../ec"],
["eclass2scrbl", "../eclass2scrbl"],
["ecmascript", "../ecmascript"],
["ee-lib", "../ee-lib"],
["effection", "../effection"],
@ -296,6 +299,7 @@ var link_dirs = [
["font-finder", "../font-finder"],
["for-helpers", "../for-helpers"],
["foreign", "../foreign"],
["forged-ocelot", "../forged-ocelot"],
["formatted-string", "../formatted-string"],
["forms", "../forms"],
["forth", "../forth"],
@ -409,6 +413,7 @@ var link_dirs = [
["inexact-number-lang", "../inexact-number-lang"],
["infix-manual", "../infix-manual"],
["infix-syntax", "../infix-syntax"],
["ini", "../ini"],
["inside", "../inside"],
["interactive-brokers-api", "../interactive-brokers-api"],
["interconfection", "../interconfection"],
@ -492,6 +497,7 @@ var link_dirs = [
["magenc", "../magenc"],
["magnolisp", "../magnolisp"],
["main", "../main"],
["majordomo2", "../majordomo2"],
["make", "../make"],
["make-log-interceptor", "../make-log-interceptor"],
["manual-flomat", "../manual-flomat"],
@ -728,6 +734,7 @@ var link_dirs = [
["racket-paint", "../racket-paint"],
["racket-quandl", "../racket-quandl"],
["racket-route-match", "../racket-route-match"],
["racket-tree-sitter", "../racket-tree-sitter"],
["racket_turtle", "../racket_turtle"],
["racketscript", "../racketscript"],
["racketui", "../racketui"],
@ -801,6 +808,7 @@ var link_dirs = [
["rokit-racket", "../rokit-racket"],
["roman-numeral", "../roman-numeral"],
["roomba", "../roomba"],
["rosette-guide", "../rosette-guide"],
["routy", "../routy"],
["rparallel", "../rparallel"],
["rpn", "../rpn"],
@ -814,6 +822,7 @@ var link_dirs = [
["ruckus", "../ruckus"],
["runomatic", "../runomatic"],
["russian", "../russian"],
["russian-lang", "../russian-lang"],
["rws-html-template", "../rws-html-template"],
["rx-tx-async-channel", "../rx-tx-async-channel"],
["s3-sync", "../s3-sync"],
@ -1142,7 +1151,7 @@ function demand_load(p, callback) {
var loaded_link_targets = [];
var link_targets = [];
var num_link_target_bins = 20;
var num_link_target_bins = 21;
function convert_all_links() {
var elements = document.getElementsByClassName("Sq");
@ -1166,7 +1175,7 @@ function convert_all_links() {
}
}
if (tag) {
var v = hash_string(decodeURIComponent(tag[0].substring(4))) % 20;
var v = hash_string(decodeURIComponent(tag[0].substring(4))) % 21;
if (!loaded_link_targets[v]) {
loaded_link_targets[v] = true;
var p = "../local-redirect/local-redirect_" + v + ".js";

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show more