Namespace and file structuring

320 views
Skip to first unread message

Terje Dahl

unread,
Mar 25, 2011, 1:05:17 AM3/25/11
to Clojure
I would love to know how better to organize my code:
I understand the basics of namespaces and how to use them.
But when and why I should use different namespaces eludes me.

In Java, the language forces you to have more or less one class pr
class-file, and you are encouraged to group class-files in packages.
So, is it as simple as saying that that namespaces are analogous to
class-files, and clj-files are analogous to packages?

But then Java doesn't have anything like rebinding something from one
namespace into another, for one.
What are the best ways to use namespaces?

Also, while we are at it, what are the naming conventions?
The same as in Java packages?
So I would use: "no.terjedahl.some.namespace.here" ?


I would love to here thoughts on this.
And any links to web-pages discussing the topic.

Stuart Sierra

unread,
Mar 25, 2011, 6:00:20 PM3/25/11
to clo...@googlegroups.com
I try to use namespaces in layers.  Each namespace defines an "interface" as a set of functions, and only calls functions of the layer(s) "below" it.  I build from small utilities and Java interop at the "bottom" layer, to application-level logic in the "middle" layers, with the external API in the "top" layer.

This helps with the one hard-and-fast rule of Clojure namespaces: no circular dependencies.  If namespace A depends on namespace B, then namespace B cannot depend on namespace A.

For naming, the Java package convention is pretty good at avoiding conflicts.

-Stuart Sierra
clojure.com

James Reeves

unread,
Mar 25, 2011, 6:35:12 PM3/25/11
to clo...@googlegroups.com
On 25 March 2011 01:05, Terje Dahl <te...@terjedahl.no> wrote:
> In Java, the language forces you to have more or less one class pr
> class-file, and you are encouraged to group class-files in packages.
> So, is it as simple as saying that that namespaces are analogous to
> class-files, and clj-files are analogous to packages?

Typically, each .clj file will have its own namespace. Clojure uses
the namespace to find where the corresponding .clj file is on the
classpath.

> Also, while we are at it, what are the naming conventions?
> The same as in Java packages?
> So I would use:  "no.terjedahl.some.namespace.here" ?

Some people use this convention, but the majority of Clojure libraries
tend to use the following convention:

library-name.some.namespaces

For instance, here are some namespaces for the Ring library:

ring.middleware.params
ring.util.response

You can use namespaces of only one part, such as "lancet", but this
will result in class-files without a package. As I understand it, this
is generally discouraged, so in the cases where a library only needs
one namespace part, a ".core" is usually appended, e.g. "clout.core".

I don't think there are any official recommendations, but these are
the conventions used by many Clojure libraries, and build tools like
Leiningen.

- James

Ken Wesson

unread,
Mar 25, 2011, 6:42:48 PM3/25/11
to clo...@googlegroups.com
On Fri, Mar 25, 2011 at 6:00 PM, Stuart Sierra
<the.stua...@gmail.com> wrote:
> I try to use namespaces in layers.  Each namespace defines an "interface" as
> a set of functions, and only calls functions of the layer(s) "below" it.  I
> build from small utilities and Java interop at the "bottom" layer, to
> application-level logic in the "middle" layers, with the external API in the
> "top" layer.
>
> This helps with the one hard-and-fast rule of Clojure namespaces: no
> circular dependencies.  If namespace A depends on namespace B, then
> namespace B cannot depend on namespace A.

Unless you use dependency injection tricks. E.g.:

(ns foo)

(def somemap (atom {}))

(defn foo-inject [k v]
(swap! somemap assoc k v))

(defn foo-dosomething [a b c]
(let [d ((@somemap :injected-fn) a)]
...))

...

(ns bar)

(defn some-fn [a]
...
... depends indirectly on foo-dosomething,
... but avoids unbounded recursion if called
... by foo-dosomething
...)

(defn bar-init []
(foo/foo-inject :injected-fn some-fn)
...)


As long as bar-init is called before anything that calls
foo-dosomething/bar-init/etc., and the some-fn/foo-dosomething
recursion remains bounded, this is OK.

I had this come up recently in connection with a fairly complex system
that had to bootstrap itself. There was a low-level DAL that had to
fall back on certain in-memory defaults, which had to hold references
to functions that operated at a much higher level, eventually calling
a lookup function in some cases that depended in turn on the low-level
DAL. Cramming the DAL, the lookup engine, and some higher level
abstractions into a single namespace seemed excessive, and I wanted
these as three separate layers, but then the lowest of these layers
needed maps containing objects containing functions defined in the
highest.

To be exact, the lookup engine knows natively how to search data of
type X. But the system is extensible to be able to search data of
types Y, Z, etc. with the added search know-how being itself supplied
as data of type X. So the lookup engine uses the type of search to
first look up the appropriate lookup engine, if the type isn't X. This
leads to the lookup engine calling the DAL, which in turn needs to be
able to supply the "how to search for stuff" data of type X as soon as
the system has started up, which data needs to contain information on
searching for data of type Y as that's built in and not user-defined
and needed at a higher level of the system, and that information
contains search functions themselves, which punt to the lookup engine
...

The only alternative to the in-memory bootstrap procedure noted above
would be to rely on certain disk files being created ahead of the
first execution of the program on a new system. With the bootstrap
procedure, the system can easily generate the disk files if they're
absent, can usually recover if they get scrogged (and certain files
can be deleted to make it recover otherwise), and can eschew wasting
disk space storing "what it already knows", including only user-added
information in disk files.

For managing circular dependencies in general, the only alternative to
using a mutable of some sort to inject them is to defer their
resolution to runtime. Example 1:

(ns foo)

(defn foo-dosomething [a b c]
(let [d ((@(ns-resolve 'bar 'some-fn)) a)]
...))

...

(ns bar)

(defn some-fn [a]
...
... depends indirectly on foo-dosomething,
... but avoids unbounded recursion if called
... by foo-dosomething
...)

This variation just finds some-fn in namespace bar at runtime, so ns
foo will compile without ns bar, ns bar can then be compiled, and then
at runtime everything works. If things are slowed too much at runtime
in foo-dosomething, the resolution can be cached:

(ns foo)

(def some-fn (atom nil))

(defn foo-dosomething [a b c]
(let [f @some-fn
f (if f f (reset! some-fn @(ns-resolve 'bar 'some-fn)))
d (f a)]
...))

or you can define and use a memoized function that wraps @(ns-resolve x y).

If there are going to be many of these calls in your codebase you will
want to sugar things up:

(defn lookup [sym]
@(ns-resolve (symbol (namespace sym)) (symbol (name sym))))

(def lookup (memoize lookup))

(defmacro use [sym & args]
`((lookup (quote ~sym)) ~@args))

...

(ns foo)

(defn foo-dosomething [a b c]
(let [d (use bar/some-fn a)]
...))

This is nearly as nice as apply, though you have to fully qualify the
symbol bar/some-fn. The downside is, no compile time checking for
typos etc.; if there's no bar/some-fn at runtime you'll get an NPE
thrown out of lookup when foo-dosomething is called, as ns-lookup will
return nil and (deref nil), well ...

Terje Dahl

unread,
Mar 28, 2011, 3:01:26 AM3/28/11
to Clojure


On Mar 26, 12:35 am, James Reeves <jree...@weavejester.com> wrote:
> On 25 March 2011 01:05, Terje Dahl <te...@terjedahl.no> wrote:
>
> > In Java, the language forces you to have more or less one class pr
> > class-file, and you are encouraged to group class-files in packages.
> > So, is it as simple as saying that that namespaces are analogous to
> > class-files, and clj-files are analogous to packages?
>
> Typically, each .clj file will have its own namespace. Clojure uses
> the namespace to find where the corresponding .clj file is on the
> classpath.

So, would you say that namespaces are in fact a lot like Python
packages - one pr file - and with the same flexibility of Python's
import-statements:

import foo.bar
from foo import bar
import foo.bar as mything
etc.

What has thrown me, has been the apparent haphazard use of namespaces
in tutorials using REPL ...


> > Also, while we are at it, what are the naming conventions?
> > The same as in Java packages?
> > So I would use:  "no.terjedahl.some.namespace.here" ?
>
> Some people use this convention, but the majority of Clojure libraries
> tend to use the following convention:
>
>   library-name.some.namespaces
>
> For instance, here are some namespaces for the Ring library:
>
>   ring.middleware.params
>   ring.util.response

Ah, but as in Java, the "big official libraries" such as java itself
starts with i.e. java.swing. But if I was to publish a utilities
library for swing, i would call it no.terjedahl.java.swing, so that it
could be used by me or others as-is, without conflict with java.swing.
So, I tend to agree with Stuart Sierra in his statement: "For naming,

James Reeves

unread,
Mar 28, 2011, 8:50:05 PM3/28/11
to clo...@googlegroups.com
On 28 March 2011 03:01, Terje Dahl <te...@terjedahl.no> wrote:
> So, would you say that namespaces are in fact a lot like Python
> packages - one pr file - and with the same flexibility of Python's
> import-statements:

Basically, yes. It's possible to put different namespaces in the same
file, but then the `require` and `use` functions wouldn't work.

> Ah, but as in Java, the "big official libraries" such as java itself
> starts with i.e. java.swing.  But if I was to publish a utilities
> library for swing, i would call it no.terjedahl.java.swing, so that it
> could be used by me or others as-is, without conflict with java.swing.

In theory this is a problem, but in practise it rarely is. Many
languages don't prefix their namespaces with domain names, such as
Ruby and Python, and they manage fine. Also, if your library doesn't
have a unique name (within the context of a language) it's confusing
for users and search engines, even if you can make the namespace
unique.

So in most cases, prefixing the domain on the namespace is
unnecessary, and it ties you to one domain. What happens if you move
domain, or someone else takes over the project? In my personal view,
the domain prefix looks rather unprofessional, though I guess that's a
matter of taste :)

- James

Mike Meyer

unread,
Mar 29, 2011, 12:40:09 AM3/29/11
to clo...@googlegroups.com
On Mon, 28 Mar 2011 20:50:05 -0400
James Reeves <jre...@weavejester.com> wrote:

> > Ah, but as in Java, the "big official libraries" such as java itself
> > starts with i.e. java.swing.  But if I was to publish a utilities
> > library for swing, i would call it no.terjedahl.java.swing, so that it
> > could be used by me or others as-is, without conflict with java.swing.
> In theory this is a problem, but in practise it rarely is. Many
> languages don't prefix their namespaces with domain names, such as
> Ruby and Python, and they manage fine.

Mostly fine, anyway. I've seen more than one Python private library
that unintentionally collided with standard library modules the author
didn't use and wasn't aware of. Trying to use both modules in the same
application was - um, interesting.

<mike
--
Mike Meyer <m...@mired.org> http://www.mired.org/consulting.html
Independent Software developer/SCM consultant, email for more information.

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

Laurent PETIT

unread,
Mar 30, 2011, 11:57:37 AM3/30/11
to clo...@googlegroups.com, Mike Meyer


2011/3/29 Mike Meyer <m...@mired.org>

On Mon, 28 Mar 2011 20:50:05 -0400
James Reeves <jre...@weavejester.com> wrote:

> > Ah, but as in Java, the "big official libraries" such as java itself
> > starts with i.e. java.swing.  But if I was to publish a utilities
> > library for swing, i would call it no.terjedahl.java.swing, so that it
> > could be used by me or others as-is, without conflict with java.swing.
> In theory this is a problem, but in practise it rarely is. Many
> languages don't prefix their namespaces with domain names, such as
> Ruby and Python, and they manage fine.

Mostly fine, anyway. I've seen more than one Python private library
that unintentionally collided with standard library modules the author
didn't use and wasn't aware of. Trying to use both modules in the same
application was - um, interesting.



Especially since clojure namespaces aren't modules : they can't be loaded in memory under a specific "name" for a specific namespace, while another "version" could be loaded in memory under another specific "name" for another namespace.
 
   <mike
--
Mike Meyer <m...@mired.org>              http://www.mired.org/consulting.html
Independent Software developer/SCM consultant, email for more information.

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply all
Reply to author
Forward
0 new messages