Once again, I have to apologise for a stupidly long and stupidly late
reply. I've tried to make this thing a little more digestible by
chopping it into three chunks. In order to keep any replies together,
I suggest that people reply to the third part unless the reply is very
specific to one of the other parts. This first part is (I hope)
relatively fun.

First of all: I'll refer to 'relation-directories' as
'link-directories' from now on; the new term should be more
enlightening and less misleading. (Sorry if the change causes any
temporary confusion.) Again, each link-directory expresses one
instance of a relation; in RDB terms that's one tuple of a relation or
one row of a table, while in OO theory terms it's one link of a
relation. (In fact that's not completely and invariably true, because
of the "weakly-typed" nature of link-dirs.) The directory which (by
definition) has as its children every link-directory of a given type
is *not* a link-directory. (It is an ordinary predicate-directory.) In
RDB terms it is the table, and its children are its rows. In OO terms
it is the relation (which makes it a class) and its children are the
links of that relation (the objects which are instances of the
relation).

Second, in the coming examples, assume that the present working
"directory" can be set to any "name", those of ordinary atomic files
as well as those of link- and predicate-directories. This isn't
essential to anything that follows, but it does make things more tidy.
The ability to list the path"names" of a given file makes it useful to
have the pwd point to an atomic file: a command, say

$ ls -P

, can list (some of) the parents of the current file, whether or not
it is a directory. The change also creates consistency with
link-directories, which are non-(predicate-)directory files that can
be the target of the pwd.

On 5/28/05, Alexander G. M. Smith <[EMAIL PROTECTED]> wrote:
> Leo Comerford wrote on Wed, 18 May 2005 12:50:38 +0100:
> > But if you have relation-directories and the ability to find the
> > pathnames of a given file, you can do everything you can do with
> > subfiles, just as nicely, and more besides. And if subfiles are
> > completely redundant and bad news anyway, we shouldn't have them.
>
> I prefer subfiles (or fildirutes) as being easier to understand.  But
> maybe that's just due to lots of experience with using file hierarchies.
> I can see having a relational system, but I'd always want to also have
> a directory hierarchy namespace, so that all files can be named.
>
> Having those relationship directories seems kind of clunky - since
> they're not located near the object being investigated.  Though
> that's a GUI matter of making/(something)/friend the system file browser pop 
> up a
> "Show Relationships..." menu item as contrasted with drilling down
> to a subfile directory listing by clicking on an item.

I'll start with an example here. Imagine a directory,

/(whatever)/portrait

, in which there are portrait photos of a number of men, one photo per
man. Each photo is identified under /(whatever)/portrait by the guy's
first name, so you have

/(whatever)/portrait/Mike
/(whatever)/portrait/Bob

and so on. Now suppose we use link-directories to express father/son
relationships between the guys in the photos. So, for example, if Mike
is Bob's father, we could have

/(something)/father-son/
/(something)/father-son/aardvark:
/(something)/father-son/aardvark:father (which is the file also known
as '/(whatever)/portrait/Mike')
/(something)/father-son/aardvark:son (the file also known as
'/(whatever)/portrait/Bob')

Using these link directories, we can easily express the information in
this (father's-side) family tree:

                                          --------   Mike  --------
                                          |                       |
                                          v                       v
                                 ------- Bob ------              Ted
                                 |        |       |               |
                                 v        v       v               v
                                Joe      Dean    Ed              Todd

, where Mike ----> Bob means "Mike is the picture of the father of the
guy pictured in Bob".

But this is where the clunkiness comes in. The family-tree
representation above is an obvious and natural way to conceive of and
manipulate the father/son relationships. We want there to be a
father-son link straight from Mike to Bob; what's more, we want to be
able to list the children (in the graph sense!) of Mike and see Bob
and Ted, and to move leafward from Mike to Bob or rootward from Bob to
Mike. But when we look at how we expressed the information using
link-directories, we see this instead:

        --------------- /(something)/father-son/ --------
        |                                               |
        v                                               v
    aardvark -----------------                     -- zebra ---
    |                        |                     |          |
    |:son                    |:father       :father|          |:son
    |                        |                     |          |
    v                        v                     v          v
(/(whatever)/portrait/Bob) (/(whatever)/portrait/Mike)
(/(whatever)/portrait/Ted)

... and so on for the other relationships. All the information in our
family tree is present and correct, but the way we chose to express it
has almost completely vanished. There is no link to follow from Mike
to Bob; instead we have to

1) find the /(something)/father-son/(animal name):father path"name"s
of /(whatever)/portrait/Mike
2) for each of the /(something)/father-son/(animal name) directories:
    2.1) find the /(whatever)/portrait/* path"name" of (animal name):son
    2.2) iff it's /(whatever)/portrait/Bob:
        2.2.1) success: cd /(something)/father-son/(animal name):son and stop
3) failure: announce failure and stop

That's easy to do; it's just a handful of ls es and optionally some cd
s. But it's going to get boring fast. More importantly, what we really
want to do is to be able to examine and move around the family tree in
just the same way that we ls and cd around the directory tree (or
rDAG, and in fact with link-directories it won't even always be
acyclic). But the edges in our family tree have become nodes in their
own right, in the form of the link-directories. In fact, there's
nothing to indicate that the family tree is a tree at all.

Oh well. At least we can save ourselves some physiotherapy by writing
a shell program that will allow us to move from father to son in a
single command. So, when the pwd is /(whatever)/portrait/Mike and we
give our command the argument 'Bob', it will use the procedure above
(plus some error-checking if we're being thorough) to change the pwd
to /(whatever)/portrait/Bob . So now we can do

$ cd /(whatever)/portrait/Mike
$ pwd
/(whatever)/portrait/Mike
$ cg Bob
$ pwd
/(whatever)/portrait/Bob

cg stands for 'change guy', of course. :) That improves things
somewhat. It won't be hard to add a command to list a man's sons:

$ lsg
Joe Dean Ed

What about his father?

$ gd
Mike

But we could take this further: since every man is a member of a tree
of father-son relationships, we could use an equivalent to filesystem
pathnames to express its position in the tree. So, if we use ls -P to
list the absolute pathnames of a file, we can also have lsg -P:

$ ls -P
/(whatever)/portrait/Bob
/(something)/father-son/aardvark:son
[etc. etc.]
$ lsg -P
^Mike-Bob

where the ^ indicates that Mike is a root, since we haven't entered a
father for him, and that Bob is his son. Then, finally, how about
these?

$ cg ..
$ lsg -P
^Mike
$ cg ^Mike-Ted-Todd
$ lng /(whatever)/portrait/Andy; lsg -P .-Andy
^Mike-Ted-Todd-Andy
$ cg ^ ; lsg -P
^Mike

Using cg, lsg and so on, the link-directory nodes appear as edges
between father and son, and the predicate-directories (such as
/(whatever)/portrait and /(something)/father-son ) disappear entirely.
So the tree is back. After we expressed the family tree in terms of
the filesystem "tree", we then built operators for the family tree out
of the operators for the filesystem "tree". That allows us to examine
and manipulate the family tree, as a tree, just as if it were
hardwired into the filesystem API. Looking at the family tree using
the low-level filesystem operators is like examining a JPEG file using
a hex debugger; of course what you see is not going to look anything
like the picture. The specialised operators provide the equivalent of
a JPEG viewer. And they're pleasingly "first-order" - just as much
"real" filesystem operators as ls, cd and so on. Not only are they
accessed through the same interface(s), but they move the same pwd
around, allowing us to freely intermix cg s and cd s, lsg s and ls es.

(Of course, this approach (build the data structures out of existing
types, then build the operators out of existing operators) is also
basically how you create a new type in a high-level programming
language. So it's not a very new or difficult insight, though
apparently it passed these people by

http://www.birdstep.com/database/collaterals/Publication%20-%20Network%20and%20Relational%20Data%20Modeling%20(2004_01_01).pdf

and even eluded our industry leader

http://www.microsoft.com/windows2000/techinfo/howitworks/activedirectory/dsvsrd.asp

.)

We can of course take things further. For one thing, inventing and
remembering cute names for the operators on one type of link-directory
isn't hard, but it doesn't scale when we add operators for many other
types. So we can do with generic operators. For example, consider a
set of generic operators for inspecting and editing data as a tree, or
more precisely as a rooted digraph which may or may not be acyclic or
a tree. ch is the generic equivalent to cd or cg , and there are
equivalent equivalents (ahem) for ls/lsg, pwd/pwg and so on. So

$ ch -t /(something)/father-son ..

is equivalent to

$ cg ..

; the the -t argument tells ch to use the tree-browsing conventions
associated with the /(something)/father-son link-directories.
(Obviously ch could do this by invoking cg.) But naturally ch as used
above is too clunky to type regularly, so we could use

$ deftree /(something)/father-son

which sets the default value of -t for the generic tree operators,
after which we can simply type

$ ch ..

instead.

(It should go without saying that programs wouldn't have to use the
new operators by hauling text through standard IO. Part of every set
of rooted-digraph operators would be a library providing function
access to the filesystem "tree" presented by those operators - these
calls would of course be standard across different sets of
rooted-digraph operators, and probably identical to the corresponding
syscalls for the base fileysystem. The only library most programs
would have to load or compile would be that provided by the generic
rooted-digraph operators, which would multiplex between the different
operator-sets' calls in a manner similar to deftree or ch -t .)

The generic operators are quite a nice bit of abstraction. For
example, you could build a GUI tree/rooted-digraph browser as a skin
over ch and friends. Then, just as ch and friends provide a uniform
command-line interface to the tree representations of different file
relationships, the browser will automatically provide a visualisation
and graphical interface for them all - a semantically-aware GUI
relationship-browser rather than yet another single-purpose, ad-hoc
tool for slogging through the base filesystem tree. For example, you
could set it to /(something)/father-son mode and see the family tree,
complete with direct links between father and son, and nothing else.
Or you could show the family tree decorated with additional
information from the base filesystem tree, or vice versa.

(Continuing the JPEG-format analogy, today's filesystem browers do of
course display JPEGs and suchlike, but while they only provide
semantically-aware viewing of individual files (showing a JPEG file as
a JPEG thumbnail, a text file as the start of the text, etc.) our
relationship-browser provides the same for the relationships /between/
files. (Which is actually not so different, since link-directories
both describe relationships between files and in so doing constitute
compound files themselves.)

Now this is all fine, but we still need to create the equivalent of
cg, lsg and so on for each of the relations we define before the
filesystem can provide a high-level interface to them. Quite a bore if
we just want to lash up something quickly. Well, one legitimate
solution is simply not to bother creating the operators; nowhere is it
written that every relation must have a high-level interface. Perhaps
we will write operators for it later if it becomes worthwhile. But not
writing the operators leaves us clunking around in the low-level
representation of our relation; we need a truly lazy solution.

Well, every /(something)/father-son link-directory always has two
children, one named :father and the other :son. In the higher-level
tree interface we want to build, every link-directory represents a
parent-child relationship (in the graph sense), with the :father file
as the parent. Now, relations like that are going to be two a penny.
Instead of writing a different set of high-level tree operators for
/(something)/father-son and every relation like it, we can write an
universal implementation which can provide the operators for all of
them. (Don't confuse this with ch and so on, which provide a generic
/interface/ to the tree operators, so users don't have to remember
that the cd-equivalent for /(something)/father-son is called cg.) So
instead of writing code for cg etc. we can just give the universal
implementation the information it needs to cover 
/(something)/father-son . The most important information the universal
implementation will need is what the two role-names are and which one
we want to present as the parent in the default semantic-level tree
interface. For nice name segments in the pathnames we should also
provide the name of some directory of which every one of the node
files is a child, such as /(whatever)/portrait for father-son. An
obvious way to provide this information would be to put the
information in a simple text file connected by a link-directory to
/(something)/father-son/ .

So now creating the new parent-child relation, complete with swishy
semantic-level integration to everything, is down to roughly a handful
of cd s and ln s and an echo . Of course, we can do better than that.

$ trel /(something)/father-son :father :son -d /(whatever)/portrait -o
cg lsg pwg lng [etc.]
$

Called thus, trel creates /(something)/father-son/ (if necessary) and
links to it the text file with the information for the universal
implementation of the high-level operators. The role-names are :father
and :son ; :father is made the parent role as it came first. The -d
option specifies /(whatever)/portrait as the name-segment directory.
The -o option takes a list of custom names for the operators; if it is
omitted, the operators can still be accessed using deftree and ch -t ,
and of course custom names can be added later. -d can be omitted. The
role-names can be omitted too, in which case trel uses the role-names
:parent and :child . The first argument specifying the
relation-directory can be replaced by -q foo, in which case the
relation-directory /(stuff)/quickrel/foo is created if necessary. And
finally,

$ trel -q foo . ../bar
$

not only creates /(stuff)/quickrel/foo/ if necessary, but also gives
the pwd the path /(stuff)/quickrel/foo/aardvark:parent and makes
../bar :child . It is equivalent to

$ qtr foo ../bar
$

You can naturally link to an existing directory from
/(stuff)/quickrel/ if you want. Of course, if we know that
/(something)/father-son has already been set up, we can also simply
say

$ cd /(whatever)/portrait/Mike
$ deftree /(something)/father-son
$ lk ../Bob
$

where lk is the generic ln/lng/etc. operator.

But enough. The point is made: a few well-chosen utilities make
link-directories convenient and unclunky, especially for simple tasks.

--
Leo Richard Comerford - http://www.st-and.ac.uk/~lrc1 - accept no namesakes :)

Reply via email to