Not Your Daddy's Namespaces

311 views
Skip to first unread message

bc

unread,
Oct 29, 2008, 12:23:49 PM10/29/08
to Clojure
Hi all,

I've posted a new article on my blog about Clojure Namespaces:
http://bc.tech.coop/blog/081029.html

I would appreciate any comments/criticisms or additional insights.

Thanks,
Bill

Stuart Halloway

unread,
Oct 29, 2008, 12:44:52 PM10/29/08
to clo...@googlegroups.com
Hi Bill,

Good stuff. You might also mention that when you actually switch to a
namespace using the ns macro, clojure gets referred, giving you a
bunch more stuff:

(create-ns 'test)
#=(find-ns test)
user=> (count (ns-map 'test))
96
user=> (ns test)
nil
test=> (ns user)
nil
user=> (count (ns-map 'test))
513

Cheers,
Stuart

Bill Clementson

unread,
Oct 29, 2008, 2:03:31 PM10/29/08
to clo...@googlegroups.com
Hi Stuart,

Thanks, that's good to know - I didn't realize the ns macro did that!
I just had a look at the docstring for ns:

"Sets *ns* to the namespace named by name (unevaluated), creating it
if needed. references can be zero or more of: (:refer-clojure ...)
(:require ...) (:use ...) (:import ...) (:load ...) with the syntax
of refer-clojure/require/use/import/load respectively, except the
arguments are unevaluated and need not be quoted. If :refer-clojure
is not used, a default (refer 'clojure) is used. Use of ns is preferred
to individual calls to in-ns/require/use/import:

(ns foo
(:refer-clojure :exclude [ancestors printf])
(:require (clojure.contrib sql sql.tests))
(:use (my.lib this that))
(:import (java.util Date Timer Random)
(java.sql Connection Statement))
(:load \"/mystuff/foo.clj\"))"

It appears that ns provides a lot of "convenience" functionality!

Cheers,
Bill

Rich Hickey

unread,
Oct 29, 2008, 4:20:38 PM10/29/08
to Clojure


On Oct 29, 2:03 pm, "Bill Clementson" <billc...@gmail.com> wrote:
> Hi Stuart,
>
> Thanks, that's good to know - I didn't realize the ns macro did that!
> I just had a look at the docstring for ns:
>
> "Sets *ns* to the namespace named by name (unevaluated), creating it
> if needed. references can be zero or more of: (:refer-clojure ...)
> (:require ...) (:use ...) (:import ...) (:load ...) with the syntax
> of refer-clojure/require/use/import/load respectively, except the
> arguments are unevaluated and need not be quoted. If :refer-clojure
> is not used, a default (refer 'clojure) is used. Use of ns is preferred
> to individual calls to in-ns/require/use/import:
>
> (ns foo
> (:refer-clojure :exclude [ancestors printf])
> (:require (clojure.contrib sql sql.tests))
> (:use (my.lib this that))
> (:import (java.util Date Timer Random)
> (java.sql Connection Statement))
> (:load \"/mystuff/foo.clj\"))"
>
> It appears that ns provides a lot of "convenience" functionality!
>
> Cheers,
> Bill
>
> On Wed, Oct 29, 2008 at 9:44 AM, Stuart Halloway
>
> <stuart.hallo...@gmail.com> wrote:
>
> > Hi Bill,
>
> > Good stuff. You might also mention that when you actually switch to a
> > namespace using the ns macro, clojure gets referred, giving you a
> > bunch more stuff:
>
> > (create-ns 'test)
> > #=(find-ns test)
> > user=> (count (ns-map 'test))
> > 96
> > user=> (ns test)
> > nil
> > test=> (ns user)
> > nil
> > user=> (count (ns-map 'test))
> > 513
>
> > Cheers,
> > Stuart
>
> >> Hi all,
>
> >> I've posted a new article on my blog about Clojure Namespaces:
> >>http://bc.tech.coop/blog/081029.html
>
> >> I would appreciate any comments/criticisms or additional insights.
>

A quick couple of things:

Your post refers to symbols in a few places where it should say vars.
Unlike CL, symbols are just names, with no associated values. The
things that are more like symbols from that perspective in Clojure are
vars, and it is vars that are interned in namespaces. Two symbols with
the same name can be distinct objects. A namespace is not a set of
symbols but a set of mappings from symbols to references - either vars
or classes.

This separation of concerns is an important part of how Clojure is a
Lisp-1 while still supporting defmacro semi-hygienically. The reader
reads plain symbols and does no interning. The compiler resolves names
(symbols) in the compilation namespace in order to find vars/classes.
def interns new vars, and import/refer/use can make new mappings.

ns is the preferred way to define/setup a namespace (think defpackage)
- it is more declarative. But it is intended to be used once only.
Using in-ns as you did is the right way to change namespaces at the
repl - ns is not for that.

I can explain more later, but wanted to clarify these points a bit.

Rich

Bill Clementson

unread,
Oct 29, 2008, 5:05:55 PM10/29/08
to clo...@googlegroups.com

Thanks for the clarifications - I've updated my blog post to use "var"
instead of "symbol" and I've added both your comments and Stuart's
comments as updates to the blog post.

Bill

Michael Wood

unread,
Nov 1, 2008, 10:24:08 AM11/1/08
to clo...@googlegroups.com
Hi

Your backslashes have gone missing in your calls to printf. e.g.:

(doseq x (ns-map 'test) (printf "%s: %sn" (first x) (frest x)))

--
Michael Wood <esio...@gmail.com>

Bill Clementson

unread,
Nov 2, 2008, 8:06:28 PM11/2/08
to clo...@googlegroups.com
Hi Michael,

Arrggh! I hate it when that happens! I forget to escape backslashes in
PRE blocks way too often. Thanks for letting me know.

- Bill

Reply all
Reply to author
Forward
0 new messages