clarify different link functions in clojure

A great useful tutorial and I am there to make this summary.

refer

refer takes a symbol argument and maps all the public symbols from that namespace into the current namespace.
The symbols are still mapped to the values in their original namespace. By calling refer in the example, you created a namespace mapping from the symbol greetings/println to the Var #'clojure.core/println.

1
2
3
(clojure.core/refer 'clojure.core)
(refer 'clojure.core :exclude '(map set))
(refer 'clojure.core :only '(println prn))

require

To link another class/function with our namespace, but its own namespace kept. Needs canonical namespace to invoke.
Loads libs, skipping any that are already loaded. Each argument is either a libspec that identifies a lib, a prefix list that identifies multiple libs whose names share a common prefix, or a flag that modifies how all the identified libs are loaded. Use :require in the ns macro in preference to calling this directly.

1
2
3
4
5
6
7
8
user=> (require 'clojure.string 'clojure.test :verbose :reload) ;separately
user=> (require '[clojure.string :as string]) ;use alias
user=> (require '(clojure string test)) ;import NS of same root
user=> (require '(clojure [string :as string] test)) ; combination
user=> (require '[clojure.data.json :refer :all]) ; this :refer is the most encouraged method

user=> (clojure.string/join [1 2 3]) ;use ns/fn to invoke
user=> (string/join [1 2 3]) ;use alias to shorten if alias exists

As you need to use namespace/function to refer to target function.

use

To import another class/function into our namespace, hence target namespace just like merged into your namespace.
This function combined require and refer. But for recent version, they tend to deprecated use by using (require '[clojure.data.json :refer :all]).

1
2
3
4
5
6
user=> (use 'clojure.string)
user=> (use '[clojure.string :only [split]])
user=> (use '[clojure.string :exclude [replace reverse]]) ; To import all except those
;since USE will merge target ns into current ns
; [:only] option makes it possible to merge partially.
user=> (split "a,b,c" #",") ;split is a function defined in [string] ns

You just need to use function to refer to target function directly without referring namespace.

import

To import Java class into namespace and shorten the invock name.

1
2
3
(java.util.Date.) ;you could invoke this class by its canonical  name
(import 'java.util.Date)
(Date.) ;now just calling class name

You could shorten the canonical name and just need to use simple name of a class to refer to target class

namespace declare

To simply those kinds of link function, use (ns) function to bring them all together.

1
2
3
4
5
6
7
8
9
10
(ns my-great-project.core
"This namespace is CRAZY!"
(:use [clojure.string :only [split join]] :reload)
(:require clojure.stacktrace
[clojure.test :as test]
(clojure template walk)
:verbose
)
(:import (java.util Date GregorianCalendar))
)

You could use random quantity of any :use :require and :import in this function.

example

An original innovated prime number function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(ns rugal.core
"This namespace is belong to Rugal Bernstein!")
(defn aliquot? "To determine if a could be aliquoted by b"
[a b]
(= 0 (mod a b)))
(defn smallest-divisor
"Get smallest divisor of a given number"
[n]
(if (even? n)
2
(loop [i 3]
(if (aliquot? n i)
i
(recur (+ i 2))
))))
(defn prime? "To determine if given number is prime"
[n]
(if (= n (smallest-divisor n))
true
false
))

clarify different link functions in clojure
https://rug.al/2014/2014-06-13-clarify-different-link-functions-in-clojure/
Author
Rugal Bernstein
Posted on
June 13, 2014
Licensed under