thank you for that nice explanation.  It gets to the motivation ... the
problem . . . the solution.

So (to test my understanding), "use" makes symbols in another namespace part
of your namespace (adding them to your map).  Then when others 'deal'
(require or use) your namespace, that stuff you 'used' is no different to
them from the stuff you wrote (thanks to the refer on top of the require).
But if you only "require" a namespace, someone else "using" your namespace
still has to get that dependency to resolve, but they don't add that extra
stuff to their ns-map.  Is that right?  If so, stuff you only "require" is
like an implementation detail, not part of your interface (in OO terms) ...
or did I go to far with that analogy?

Thanks again.


On Fri, Jan 23, 2009 at 8:35 PM, Stephen C. Gilardi <squee...@mac.com>wrote:

>
> 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/prn
>
> This 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 loaded
>        refer   - 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 refer
>
> It 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
>
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to