On Jan 22, 2007, at 10:01 PM, Richard A. O'Keefe wrote:
> Neither. The issue is not "which order to we write dotted names", but
> "where do we START from"? Java chose absolute package names. That is
> what is bad. To take just one obvious example, suppose a group of
> classes/modules are developed by the Acme Widget company, so all those
> dotted names start out
> nz.co.acme_widget.intercal.
> Then the Acme Widget company get taken over by Southern Doohicky, Inc,
> and now we *want* the names to be
> au.com.southern_doohickey.intercal.
> Because package names are *absolute*, every dotted package name has to
> be changed. But if dotted names were *relative* to the containing
> class/
> module, only one name in the entire build would need changing.
> unnnecessarily
Ahhhh, now I understand the issue. It is certainly true that when the
developer of some code decides to change their root package name, any
application using that new code, as well as any code in the library
itself, has to redo the package imports. I seem to recall the Java
language had that happen to it at one point, but I can't remember
what it was -- I think it was Swing that changed over to using the
javax package.
I'm sure that caused the Swing developers some pain, and it cause me
pain as well.
Anyway, yes, I can definitely see the advantage of a package name
being relative.
Say I download someone's Erlang library. They decided to call it
intercal, but in order to prevent a namespace clash with other
applications that may also be called intercal, they put it in
nz.co.acme_widget.intercal -- that is, this intercal is acme_widget's
intercal, and not that other guy's intercal.
It would still be useful if I could import nz.co.acme_widget.* so
that I could use intercal.foo.bar/1 -- that is, the bar function in
the foo module in the intercal directory. The compiler would have to
do a search through the import specs to locate a valid
intercal.foo.bar/1, and if more than one were found, an error would
be generated.
But now we get your problem again -- if they decide to change their
name, I have to go through every file of mine and change import
nz.co.acme_widget.* to au.com.southern_doohickey.*, and that would
really suck if I had 100 files. Of course, that's what -include is
for :)
So the modifications would be:
0. Imports are relative to some root. That root itself may be
relative to some other root. If an import is relative to no root,
then it is in the top-level namespace.
1. Name resolution searches through the imports, either matching a
non-* import, or appending the name to a * import. If more than one
import matches, an error is generated.
2. The name of a module is relative to some root. That root itself
may be relative to some other root. If a module name is relative to
no root, then it is in the top-level namespace.
Thus, suppose we had product intercal, with the following directory
structure:
intercal/Foo.erl
intercal/Bar.erl
intercal/lower/Util.erl
intercal/lower/IO.erl
We would want Util and IO to be relative to .. (i.e. the directory
above). We would further want Foo and Bar relative to .., and we
would want intercal to be relative to nz.co.acme_widget. Note that we
don't have to go through the bother of having a directory nz/co/
acme_widget, which I've always been annoyed at :)
Now, internal to the intercal product, Util.erl can now call Foo.baz/
1, because Util is relative to .., and therefore Foo.baz should be
located in ../Foo.erl.
Furthermore, Util.erl could choose to -import(Foo). This means that
it can now call baz/1, because the name resolver found a match in ../
Foo.baz/1.
This will also result in an error if there is a top-level Foo module
with a baz/1 function, because then we don't know if you meant
Foo.baz/1 or ../Foo.baz/1. The resolution is to specify
either .Foo.baz (top-level) or nz.co.acme_widget.intercal.Foo.baz
(fully qualified) -- or maybe even something that would allow you to
specify a relative path.
It's a bit complex, now.
--Rob