Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference in Clojure between use and require

I recently started learning Clojure and I'm having a bit of difficulty wrapping my head around namespaces. As the creator of Clojure said, newcomers often struggle to get the concept right. I don't clearly understand the difference between (use ...) and (require ...). For example playing around in the REPL if I say (use 'clojure.contrib.str-utils2) I get warnings about functions in clojure.core namespace being replaced by the ones in clojure.contrib.str-utils2, but that doesn't happen when I use (require 'clojure.contrib.str-utils2). I'm not sure that I will always want to replace what's in clojure.core, so can someone point some best practices for importing external stuff and managing namespaces in Clojure?

Oh and also, when should I use :use and :require? Only inside (ns ....)?

Thanks in advance.

like image 545
teto Avatar asked Aug 04 '10 17:08

teto


1 Answers

The answer lies in the docstrings:

user> (doc use) ------------------------- clojure.core/use ([& args])   Like 'require, but also refers to each lib's namespace using   clojure.core/refer. Use :use in the ns macro in preference to calling   this directly.    'use accepts additional options in libspecs: :exclude, :only, :rename.   The arguments and semantics for :exclude, :only, and :rename are the same   as those documented for clojure.core/refer. nil 

And the long one for require:

user> (doc require) ------------------------- clojure.core/require ([& args])   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.    Libs    A 'lib' is a named set of resources in classpath whose contents define a   library of Clojure code. Lib names are symbols and each lib is associated   with a Clojure namespace and a Java package that share its name. A lib's   name also locates its root directory within classpath using Java's   package name to classpath-relative path mapping. All resources in a lib   should be contained in the directory structure under its root directory.   All definitions a lib makes should be in its associated namespace.    'require loads a lib by loading its root resource. The root resource path   is derived from the lib name in the following manner:   Consider a lib named by the symbol 'x.y.z; it has the root directory   <classpath>/x/y/, and its root resource is <classpath>/x/y/z.clj. The root   resource should contain code to create the lib's namespace (usually by using   the ns macro) and load any additional lib resources.    Libspecs    A libspec is a lib name or a vector containing a lib name followed by   options expressed as sequential keywords and arguments.    Recognized options: :as   :as takes a symbol as its argument and makes that symbol an alias to the     lib's namespace in the current namespace.    Prefix Lists    It's common for Clojure code to depend on several libs whose names have   the same prefix. When specifying libs, prefix lists can be used to reduce   repetition. A prefix list contains the shared prefix followed by libspecs   with the shared prefix removed from the lib names. After removing the   prefix, the names that remain must not contain any periods.    Flags    A flag is a keyword.   Recognized flags: :reload, :reload-all, :verbose   :reload forces loading of all the identified libs even if they are     already loaded   :reload-all implies :reload and also forces loading of all libs that the     identified libs directly or indirectly load via require or use   :verbose triggers printing information about each load, alias, and refer    Example:    The following would load the libraries clojure.zip and clojure.set   abbreviated as 's'.    (require '(clojure zip [set :as s])) nil 

They both do the same thing, but use goes the extra step and creates mappings for the stuff in the require'd namespace in the current namespace. That way, rather than doing some.namespace/name you're just referring to it as name. While this is convenient sometimes, it's better to use require or select the individual vars that you want rather than pull in the entire namespace. Otherwise, you could have issues with shadowing (where one var is preferred over another of the same name).

If you don't want to use require, but you know what vars you want out of the namespace, you can do this:

(ns whatever   (:use [some.namespace :only [vars you want]])) 

If you don't know which vars you're going to need, or if you need a lot, it's better to use require. Even when you require, you don't always have to type the totally qualified name. You can do this:

(ns whatever   (:require [some.namespace :as sn])) 

and then you can use vars from some.namespace like this: (sn/somefunction arg1 arg2)

And to answer your last question: try to only use :require and :use inside of (ns ...). It's much cleaner this way. Don't use and require outside of (ns ..) unless you have a pretty good reason for it.

like image 147
Rayne Avatar answered Sep 21 '22 07:09

Rayne