On Jan 23, 2009, at 7:12 PM, e wrote:
first explicit question: after the example lib and the bullets, I don't see why there are two different keywords, "use" and "require". Just look at the start of the sentences. They are identical. Why not just pick one of the two keywords and let "only" be a modifier when you want only certain things, and "as" be a modifier when you still want some level of qualification?
First some background:A map maintains relations between keys and values such that given a key, it can return the associated value.
Every namespace contains a map from symbols to the vars or classes they represent. You can see that map for a particular namespace using ns-map. For example:
(ns-map 'user)When the compiler sees a symbol it "resolves" it to determine which var or class it represents. If the symbol has no namespace part, one of the steps in resolving is to check the ns-map for the current namespace. For example:
user=> (get (ns-map 'user) 'prn) #'clojure.core/prnThis result indicates that in the namespace user, the symbol prn resolves to the var #'clojure.core/prn.
How did it come to pass that the ns-map for 'user contains a reference to a var in the clojure.core namespace? That kind of reference is made by clojure.core/refer which you should read about. Soon after the user namespace is created, the code that creates it calls (effectively) "(refer 'clojure.core)".
Now about require and use: require - ensures that a lib is loadedrefer - makes entries in this namespace's ns-map that are identical to (or based on) entries in the ns-map of another namespace
use - first require, then referIt would be technically feasible to get rid of "use" and only allow require and refer. It would also be feasible to add keyword commands to require that would accomplish the refer function without an explicit call to refer. The reason we have both require and use (and therefore :require and :use) is that when this was being designed, "require followed by refer" was thought to be a common enough case to warrant a name of its own.
Subsequent to the introduction of require, use, and ns, several folks noted that one can refer to other code in an "ns" form either in a way that makes it explicit what you're bringing into the new namespace or in a way that leaves it implicit. There is a preference in the example at clojure.org/libs for the style that makes the name(s) explicit.
Here's the implicit way: (ns mertz.fred (:use clojure.contrib.sql) (:use org.desilu.french))This is convenient in that any names defined in namespace clojure.contrib.sql can be used in the subsequent code without any namespace qualification, for example:
(with-connection my-db [...])In this call, with-connection resolves to #'clojure.contrib.sql.with- connection, but that's not apparent just by reading the code.
Here's the corresponding explicit way: (ns mertz.fred (:use [clojure.contrib.sql :only (with-connection)]) (:use [org.desilu.french :only (grey-poupon)]))Now it's easy to see where with-connection comes from by examining the ns form.
Being explicit takes some more work and thought and maintenance, but it does make things easier on future readers of the code.
Alternatively, if you want to bring in everything from another namespace, but still be able to tell which symbols come from which places, you can use a namespace alias to shorten up the name. It would be a real drag to type clojure.contrib.sql/with-connection every time you want to call it. However, some short prefix like "sql" wouldn't be too bad. Using a namespace alias for this looks like this:
(ns mertz.fred (:require [clojure.contrib.sql :as sql]) (:use [org.desilu.french :only (grey-poupon)])) Now at the site of the call, it's clear where with-connection came from: (sql/with-connection my-db [...])With this method, the ns-map of mertz.fred has no entries that refer to vars in clojure.contrib.sql.
Why not just pick one of the two keywords and let "only" be a modifier when you want only certain things, and "as" be a modifier when you still want some level of qualification?
It's certainly desirable to have a require that doesn't do a refer. Between require and use, require is the more basic of the two and would not go away.
To get rid of :use, it would be feasible to modify :require such that the appearance of :only, :exclude, or :rename would imply a "refer". At that point you could do what you're asking about. For cases where :only, :exclude, or :rename are desired, you could use them. For the case of bringing in the entire namespace you could write:
(:require [clojure.contrib.sql :exclude ()]) or (:require [clojure.contrib.sql :rename ()])Of those, the "exclude" version is easier to understand, but still a bit awkward. Note that it wouldn't fit in easily to write (something like)
(:require [clojure.contrib.sql :all])because all the arguments to require after the first are keyword-value pairs. One could say ":all true" or ":refer :all" but that's pretty awkward as well.
Given that it's feasible to remove "use" and ":use", the next question is whether or not it's desirable. I think "use" and ":use" are succinct and convenient, provide a non-awkward way to bring in an entire namespace's mappings, and I like the added flexibility they provide over other options such as having only "require" and ":require" or introducing ":refer".
--Steve
smime.p7s
Description: S/MIME cryptographic signature