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_storeThe 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: quotingCreate 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-maidenQualify a keyword with the current namespace (e.g. from music-store.core):
::whatever ; :music-store.core/whateverReload 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.