Clojure require vs. use
If you work in Clojure enough you'll see both require and use near the top of files, indicating the external files and functions that are needed in that particular namespace.
Let's say I want to use Ring's wrap-params function.
(ns project.core (:require [project.player.player-controller :refer [routes-handler]])) (def app-handler (-> routes-handler (wrap-params))) (defn -main [] (run-jetty app-handler {:port 3000}))
Let's say I have a test suite and I run my tests. I get an error.
java.lang.RuntimeException: Unable to resolve symbol: wrap-params in this context
I get this error because I'm attempting to invoke a function defined in a third-party library, but this namespace has no idea where to find this function. It doesn't know what wrap-params is.
Let's add a line to our code.
(ns project.core (:require [project.player.player-controller :refer [routes-handler]]) (:use ring.middleware.params))
Now it works. But what's happening? use is pulling in every single function from the ring.middleware.params library. It's as if I had all those functions defined in this namespace. That's far from ideal.
We could specify the functions we want to include with only.
(ns project.core (:require [project.player.player-controller :refer [routes-handler]]) (:use [ring.middleware.params :only [wrap-params]]))
And it works!
But let's take a couple steps back and adjust our original code a bit.
(ns project.core (:require [project.player.player-controller :refer [routes-handler]] [ring.middleware.params]))
Same error as the first time! Why? require is slightly different than use. By requiring ring.middleware.params I'm giving myself access to that namespace. Hop down further in the code and make another change and we can have this working.
(def app-handler (-> routes-handler (ring.middleware.params/wrap-params)))
Now it works! We specified the namespace where that function is defined. What if we did that from the beginning, but didn't require that namespace?
java.lang.ClassNotFoundException: ring.middleware.params
It doesn't know where to find ring.middleware.params. We can also alias the namespace to make this less verbose, yet potentially more clear.
(ns project.core (:require [project.player.player-controller :refer [routes-handler]] [ring.middleware.params :as ring])) (def app-handler (-> routes-handler (ring/wrap-params)))
That works! But for the most idiomatic solution, let's use refer, which takes a vector of functions, those you wish to pull in.
(ns project.core (:require [project.player.player-controller :refer [routes-handler]] [ring.middleware.params :refer [wrap-params])) (def app-handler (-> routes-handler (wrap-params)))
Near the top of the file we specify the function (wrap-params) and location of the function (ring.middleware.params). This allows us to invoke the function just as we would any other function that we defined in this namespace.
So overall, what's the difference between require - refer and use - only? Well, nothing really. require is more idiomatic, so it's considered best practice to include external functions by providing the library to require and specifying the individual functions to include with refer. By themselves, require loads libraries and use loads libraries and refers to their namespaces (giving you everything, which is usually/always overkill). use can also easily lead to namespace conflicts (for the exact reason I just mentioned).
Lastly, and quickly, if you hop in the REPL, you have a few options for how you can make use of all of this.
(require 'hyperion.api.set-ds! 'hyperion.api.new-datastore) (require '(hyperion.api set-ds! new-datastore)) (require '[hyperion.api.set-ds! :as ds]) (require ['hyperion.api.set-ds! :as 'ds]) (use '[hyperion.api :only [new-datastore]])
All valid syntax, all behaves similarly.
Some Helpful Stuff
Clojure Libs and Namespaces: require, use, import, and ns
Stack Overflow: Difference in Clojure between use and require
need, a unification of require and use















