On Feb 10, 2009, at 11:46 AM, Laurent PETIT wrote:

If I understand correctly your proposal, can you verify the following is true :

(ns foo.bar)
(ns foo.bar.util)
(ns foo.bar.impl)
(ns foo.bar.data)

with foo.bar decomposed in two files : foo/bar.clj and foo/bar1.clj just one file per ns, would result in the following structure :

Do you mean foo/bar/bar1.clj? I don't understand "just one file per ns" given that there are two files associated with (ns foo.bar).

/foo/bar.clj
/foo/bar/bar1.clj
/foo/bar/util.clj
/foo/bar/impl.clj
/foo/bar/data.clj

So now, /foo/bar/ holds all the declarations of namespaces of 3 segments whose prefix is foo.bar , plus all the extra files needed for namespace foo.bar ?

Assuming you meant that foo.bar is in two files foo/bar.clj and foo/ bar/bar1.clj above, the layout you gave is correct under my proposal. The ns declaration beginning "(ns foo.bar" would include a clause "(:load "bar1")".

Since it does not allow to infer by convention which file represents a lib, and which file not, I think I prefer the current way of having the possibility to keep all ns related files in the same directory, if I want to.

If you work with several libs that share common prefixes and have different numbers of segments, you are not able to infer which are libs and which which are load files--either currently or with my proposed change.

In current Clojure, consider a similar example:

(ns foo.bar)
(ns foo.bar.util)
(ns foo.bar.impl)
(ns foo.bar.data)

with foo.bar decomposed in two files : foo/bar.clj and foo/bar1.clj would result in the following structure :

/foo/bar.clj
/foo/bar1.clj
/foo/bar/util.clj
/foo/bar/impl.clj
/foo/bar/data.clj

Is foo/bar1.clj a lib or not? I don't believe you can determine that by looking at the file layout.

If you used the knowledge that only the 4 listed namespaces were in play, you would know which files are libs and which are not in both this example and the one you laid out above.

If you are proposing a naming convention like "foo_bar1.clj", you could (assuming the convention were always followed) make the determination. I consider that an ugly convention and I'm hoping it's not necessary often in practice. Note, though, that a similar convention could also be used if my proposal were adopted:

/foo/bar.clj
/foo/bar/_bar1.clj
/foo/bar/util.clj
/foo/bar/impl.clj
/foo/bar/data.clj

or

/foo/bar.clj
/foo/bar/load_bar1.clj
/foo/bar/util.clj
/foo/bar/impl.clj
/foo/bar/data.clj

Under my proposal these modified filenames have the advantage that they are automatically associated with their parent lib by the directory structure, so the naming convention does not need to repeat that association. One could, by convention, always prefix them with "load_" for example.

I think it will be rare for such a convention to be necessary. It would only come up in cases where lib names share prefixes of varying lengths--and would presumably only be a problem if those libs were not closely related.

You say you prefer the current way. The apparent justification for that is that it allows you more freedom to place files that are not libs in the same directory as the lib that loads them. Is this really a compelling advantage?

In clojure.contrib we have many unrelated libs under clojure.contrib. If lazy_seqs.clj (a lib) needed to load functions from fast_memoize.clj (a load file that defines functions in the lazy-seqs namespace), would it really be clearer/advantageous to have a layout like this:

        apply_macro.clj
        except.clj
        fast_memoize.clj
        import_static.clj
        javalog.clj
        lazy_seqs.clj
        macros.clj
        mmap.clj
        ns_utils.clj
        prxml.clj
        repl_ln.clj

rather than this a layout like this:

        apply_macro.clj
        except.clj
        import_static.clj
        javalog.clj
        lazy_seqs/
                fast_memoize.clj
        lazy_seqs.clj
        macros.clj
        mmap.clj
        ns_utils.clj
        prxml.clj
        repl_ln.clj

I think the latter is much clearer.

--Steve

2009/2/10 Stephen C. Gilardi <squee...@mac.com>

On Feb 10, 2009, at 10:04 AM, Rich Hickey wrote:


On Feb 10, 9:45 am, "Stephen C. Gilardi" <squee...@mac.com> wrote:
I came across this when updating the wikibook concepts page, Libraries
section, to be correct for current Clojure behavior.

In an early implementation of the code that handles libs, the resource
(file) for lib a.b.c was at the path "a/b/c/c.clj" within classpath.
At that time it was natural to consider "a/b/c/" as the lib's directory.

Later, the resource for the library a.b.c changed to the path "a/b/
c.clj" and the lib's directory became "a/b/".

I think the lib handling code should be changed such that the
directory associated with lib a.b.c is (again) "a/b/c/".

The advantage of this comes into focus most sharply in a ":load"
clause within "ns".

Here's the updated example from the wikibook:

      (ns example.ourlib
        (:load "ourlib/add1"
               "ourlib/otherfunc"
               "ourlib/morefuncs"))

With the change I'm proposing, this would become:

      (ns example.ourlib
        (:load "add1"
               "otherfunc"
               "morefuncs"))

Currently core.clj ends with 3 load calls to load in more pieces of
clojure.core that were each big enough to warrant a separate file.

The directory structure in src/clj/clojure is (in part):

      src/clj/clojure/
              core.clj
              core_print.clj
              core_proxy.clj
              genclass.clj

With the proposed change, this would become:

      src/clj/clojure/
              core/
                      core_print.clj
                      core_proxy.clj
                      genclass.clj
              core.clj

or, perhaps removing the "core_" prefixes:

      src/clj/clojure/
              core/
                      print.clj
                      proxy.clj
                      genclass.clj
              core.clj

There is also at least one lib in clojure-contrib that would need to
be updated.

I welcome discussion of this proposed change with the goal of entering
an issue and providing a patch. In the patch, I would also update the
doc string for clojure/require to reflect current Clojure behavior.


I think this needs more clarification as to what is meant by a lib/
root directory.  The lib .clj itself is not in this directory, but is
its same-named sibling.

Good point. Here's the current (doc load):

clojure.core/load
([& paths])
Loads Clojure code from resources in classpath. A path is interpreted as
 classpath-relative if it begins with a slash or relative to the root
 directory for the current namespace otherwise.

The phrase "root directory for the current namespace" (which I wrote long ago) is something that probably deserves more explanation and/ or an example. Note that "load" is the only place this "root directory" concept is used.

Here's a shot at an updated version that fits with this proposal:

clojure.core/load
([& paths])
Loads Clojure code from resources in classpath. A path is interpreted as classpath-relative if it begins with a slash or relative to the directory associated with current namespace otherwise. The path to the directory
 associated with a namespace is derived from the namespace name by
translating dots to slashes and hyphens to underscores. For example, the directory associated with namespace a.b-c.d is "<classpath>/a/b_c/ d/".


Also, it creates potential overlap between hierarchical namespaces,
e.g. a.b.c and a.b.c.d, where the resources of the former would be
siblings of the root .clj of the latter. Seems confusing at first
glance.

We already have this overlap. It seems to me that it is inherent in any hierarchical layout. It's already the case that looking at a ".clj" file within classpath, one doesn't know without looking inside it whether it's a lib or whether it's a piece of a lib that's loaded by ":load". Even after looking inside it, we can't distinguish whether it's a file that's loaded by a :load clause within an "ns" form, or a file somebody plans to load explicitly using a classpath-relative path.

I don't think this proposal makes this uncertainty any worse and it has the advantage I outlined of keeping things that are all logically together (pieces of a namespace that happen to be in separate files) physically together (all in a directory that's easily associated with the namespace). Also for :load vs load uncertainty, it becomes much easier to check whether it will be loaded by :load" by giving us an obvious place to look for the "ns" form that :loads it.

--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
-~----------~----~----~----~------~----~------~--~---


Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to