emacs.d/clones/lisp/clojure-doc.org/articles/language/namespaces/index.html

376 lines
26 KiB
HTML
Raw Normal View History

2022-08-24 19:36:32 +02:00
<!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>