968 lines
63 KiB
HTML
968 lines
63 KiB
HTML
<!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 &
|
|
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=></code>" or "<code>my-proj.core=></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>_<>!?*</code> (ex. <code>this->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=> "hi"
|
|
;; "hi"
|
|
user=> :foo
|
|
;; :foo
|
|
user=> [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>></code>, <code><=</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 <test> <then-this> <otherwise-this>)</code> (and in <code>and</code>, <code>or</code>,
|
|
<code>cond</code>, etc. expressions), Clojure checks if the <code><test></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>></code>, <code>>=</code>, <code><</code>, <code><=</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 & 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>[& 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 "<" i ">")])
|
|
</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
|
|
;; => 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">« Getting Started with Clojure</a>
|
|
|
|
|
|
||
|
|
|
|
|
|
<a href="../emacs/index.html">Clojure with Emacs »</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 © 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>
|