100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Namespaces and require

Learn how Clojure organizes code into namespaces and how ns, require, import, and refer control how symbols are loaded and referenced across files.

Practical ClojureBeginner8 min readJul 10, 2026
Analogies

What Is a Namespace?

In Clojure, a namespace is a first-class, named mapping from symbols to vars. Almost every source file declares exactly one namespace, and that namespace becomes the container for all the functions and values defined in the file, so nothing you define ever silently collides with something of the same name defined elsewhere.

🏏

Cricket analogy: Just as the IPL keeps every team's squad list in its own franchise ledger so 'Kohli' unambiguously means Royal Challengers Bangalore's Kohli and not someone else's, a Clojure namespace like myapp.core keeps its own symbol-to-var table so 'process' in myapp.core never collides with 'process' in myapp.utils.

Declaring a Namespace with ns

The ns macro at the top of a file declares the namespace's name and its dependencies in one place. Inside it, :require brings in other Clojure namespaces (typically aliased with :as so their vars can be referenced concisely), and :import brings in Java classes so they can be used by their short name instead of a fully qualified one.

🏏

Cricket analogy: Selecting a playing XI means naming which players you're bringing in for the match and giving some a shorter nickname on the scoreboard, rather than listing every player's full legal name every single time the scoreboard updates.

clojure
(ns myapp.core
  (:require [clojure.string :as str]
            [myapp.db :as db]
            [myapp.utils.parser :refer [parse-line]])
  (:import (java.util Date)
           (java.text SimpleDateFormat)))

(defn- format-now []
  (let [fmt (SimpleDateFormat. "yyyy-MM-dd")]
    (.format fmt (Date.))))

(defn greet [name]
  (str/join " " ["Hello," (str/capitalize name) (format-now)]))

;; At the REPL, after editing myapp.db, reload it without restarting:
(require '[myapp.db :as db] :reload)

require vs use, and Reloading at the REPL

The older (use 'ns) form, and the :refer :all option on :require, pull every public var from a namespace into scope unqualified. This is convenient for quick scripts but risky in application code: it hides where a symbol actually came from and can silently shadow an existing var. Preferring :as aliasing, or a narrow :refer [specific-fn], keeps every reference traceable back to its source namespace.

🏏

Cricket analogy: Calling in every reserve player from the whole domestic circuit onto the field creates chaos about who's actually fielding where, whereas naming only the specific all-rounder you need keeps the playing XI unambiguous.

Prefer :require with :as aliasing over :use / :refer :all in application code — it keeps the origin of every symbol traceable and avoids silent name collisions when two required namespaces happen to define a var with the same name.

Qualified Symbols and Private Vars

Any var can be referenced by its fully qualified name, namespace/symbol, which is unambiguous no matter what's currently required in the calling namespace. defn- (shorthand for defn plus ^:private metadata) creates a var that's visible only within its own namespace, giving you a simple way to hide implementation details from the rest of the codebase.

🏏

Cricket analogy: Announcing a substitute as 'Mumbai Indians' Suryakumar Yadav' rather than just 'Suryakumar' avoids confusion with any other SKY in the league, the same way a fully qualified symbol is never mistaken for another namespace's function; a team's internal fitness data stays in the dressing room.

Circular requires — namespace A requiring B while B requires A — will throw a compile-time error. If two namespaces seem to need each other, extract the shared functions into a third namespace that both can require, or restructure so the dependency flows in one direction only.

  • A namespace is a first-class mapping from symbols to vars, typically one per source file.
  • File paths mirror namespace names, with dashes in the namespace converted to underscores in the file name (myapp.utils.parser to myapp/utils/parser.clj).
  • The ns macro at the top of a file declares :require for other Clojure namespaces and :import for Java classes.
  • Use :as to alias a namespace and :refer [sym1 sym2] to pull in only specific named symbols.
  • Avoid :refer :all / (use ...) in application code; it silently pollutes the namespace and hides where a symbol came from.
  • defn- creates a private var that's only accessible within its own namespace.
  • Circular requires between two namespaces are a compile error — break the cycle by extracting shared code into a third namespace.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#ClojureStudyNotes#NamespacesAndRequire#Namespaces#Require#Namespace#Declaring#StudyNotes#SkillVeris#ExamPrep