Namespaces
Create a new namespace:
(ns music)
The new namespace is activated as the current namespace, which will hold the vars in a lookup table indexed by their symbols.
Define vars with the same name in two different namespaces:
(ns iron-maiden)
(def first-album "Iron Maiden")
(ns fates-warning)
(def first-album "Night on Bröcken")
(ns iron-maiden)
(println first-album) ; "Iron Maiden"
(ns fates-warning)
(println first-album) ; "Night on Bröcken"
Using ns
on an existing namespace does not create a new namespace,
but activates the existing one.
Use fully qualified symbols to access other namespaces:
(ns music-shop)
(println iron-maiden/first-album) ; "Iron Maiden"
(println fates-warning/first-album) ; "Night on Bröcken"
Use a namespace from the standard library, and use it to compare data objects:
(require 'clojure.data)
(clojure.data/diff {:song "The Apparition" :band "Iron Maiden" :duration "5m50s"}
{:song "The Apparition" :band "Fates Warning" :duration "3m54s"})
;; ({:duration "5m50s", :band "Iron Maiden"}
;; {:duration "3m54s", :band "Fates Warning"}
;; {:song "The Apparition"})
The diff
function returns a three-element list with
- data that only exists in the first argument,
- data that only exists in the second argument, and
- data that is common to both arguments.
Create a new Leiningen project in the shell:
lein new app music_store
The file music_store/src/music_store.clj
defines the namespace
music-store.core
and contains the following code:
(ns music-store.core
(:gen-class))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Hello, World!"))
Dashes are used for symbol names, and underscores for file names.
Create a new namespace music-store.bands
in music_store/src/music_store/bands.clj
:
(ns music-store.bands)
(def iron-maiden {:name "Iron Maiden" :founded 1975})
(def fates-warning {:name "Fates Warning" :founded 1983})
Use a namespace in the ns
declaration in music_store/src/mustic_store/core.clj
:
(ns music-store.core
(:require music-store.bands))
Unlike the standalone require
function used in the REPL, :require
declarations within ns
do not need quoting:
(:require music-store.bands) ; within ns: no quoting
(require 'music-store.bands) ; from the REPL: quoting
Create a (shorter) alias for a namespace:
(require '[music-store.bands :as bands])
Same within ns
without quoting:
(ns music-store.core
(:require [music-store.bands :as bands]))
Pull in specific symbols from another namespace:
(require '[music-store.bands :refer [fates-warning]])
(println fates-warning) ; {:name Fates Warning, :founded 1983}
Pull in all the symbols from another namespace:
(require '[music-store.bands :refer :all])
(println iron-maiden) ; {:name Iron Maiden, :founded 1975}
Use :refer :all
with caution, for it pollutes the current namespace.
Get hold of the current namespace:
(println *ns*) ; #namespace[music-store.core]
Lookup a namespace by its name:
(find-ns 'music-store.bands) ; #namespace[music-store.bands]
Discover the bindings of a namespace:
(ns-map (find-ns 'music-store.bands))
If a symbol instead of a namespace is given, ns-map
will look up the namespace:
(ns-map 'music-store.bands)
Get the namespace of a symbol:
(namespace 'music-store.bands/fates-warning) ; "music-store.bands"
Qualify a keyword with a namespace:
:music-store.bands/iron-maiden
Qualify a keyword with the current namespace (e.g. from music-store.core
):
::whatever ; :music-store.core/whatever
Reload the symbols of a namespace (force-reloads already loaded symbols):
(require :reload '[music-store.bands])
Get rid of loaded symbols:
(ns-unmap 'music-store.bands 'iron-maiden)
Define a var that resits :reload
(e.g. when initialized using a heavy function call):
(defonce fib-42 (fib 42))
Exercises
Leiningen Project
Create a new Leiningen project called fibonacci
and run the generated code.
Hint: Use lein run
to run the project from the fibonacci/
folder.
Test: lein run
shall output "Hello, World!"
.
Additional Namespace
Create a new namespace recursive
within the fibonacci
project. Implement a function called fib
that calculates the nth
Fibonacci number given the parameter n
. Use that function from the
core
namespace (src/fibonacci/core.clj
) in the -main
function
and call it with the argument 35
and output the result.
Hint: Put the file into the src/fibonacci
folder and name it
according to the namespace defined therin.
Test: The application shall output fib(35)=14930352
.
Yet Another Namespace
Create a new namespace tail-recursive
within the fibonacci
project. Re-use the tail-recursive implementation of the fib
function from chapter
5.
Now import both the recursive and tail-recursive namespaces into the
core
namespace as fib-rec
and fib-tail
, respectively. Call both
functions with the argument 35
and output the result as before.
Hint: Use :require
and :as
to define an alias name for the
namespaces.
Test: The application shall output fib(35)=14930352
twice.