Re: what's the correct behavior of directory-namestring

Richard M Kreuter via Sbcl-help <[email protected]> Thu, 31 Jul 2025 17:51:31 -0400
Newsgroups gmane.lisp.steel-bank.general
Message-ID <[email protected]>
Michał "phoe" Herda <[email protected]> wrote:

> W dniu 2025-07-31 14:14, Richard M Kreuter via Sbcl-help napisał(a):
> 
>     Correct in that Windows and Unix are different, but do you think it's
>     ideal for DIRECTORY-NAMESTRING to leave off the device for a Windows
>     pathname?
> 
> It is also correct because this is what DIRECTORY-NAMESTRING is defined to do
> - see 
> http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/fun_namestrin_h-namestring.html
> . Returning the device in addition to the directory would violate the
> language specification.

I don't think this is so clear. The standard says

   DIRECTORY-NAMESTRING returns the directory name portion. 

ANSI doesn't define the phrase, "the directory name portion". How should
we interpret it? I'll agree it could mean "the namestring representation
of the directory component", but, y'know, the sentence doesn't mention
components, even though the immediately preceding sentence about
FILE-NAMESTRING does. Do the different constructions signify anything? I
suppose that's up to whoever's reading the standard.

In particular, I don't see an argument that the phrase cannot mean "the
portion of the pathname that names a directory (as in a specific thing
in the file system)". For an MS-DOS-style Windows pathname with a
non-NIL device, such as #P"Z:\\foo\\bar.txt", ISTM that each of
"Z:\\foo\\" and "\\foo\\ can be said to name a directory in the file
system, though the first one is a more precise name for the directory,
since the second one only sometimes refers to that particular
object. Anyhow, ISTM either string would be a valid result from
DIRECTORY-NAMESTRING, if that's how you understand "the directory name
portion".

> As for "ideal", what is the actual intent here? Get the whole
> namestring? # 'NAMESTRING will do fine in that case.

Well, you used the word "correct", and now I think you believe there's a
unique conforming answer to what

  (directory-namestring "z:\\foo\\bar.txt")

should return. I think there are multiple conforming options, and I'd
like to reserve "correct" to one conforming option that's better than
others. So I switched to "ideal". :-)

Specifically, ISTM that if you have "z:\\foo\\bar.txt", you might want
each of

(a) an operator that will get you "Z:\\foo\\",

(b) an operator that will get you just "\\foo\\".

If DIRECTORY-NAMESTRING is (a), (b) should probably just be

  (lambda (pn)
    (directory-namestring
     (make-pathname :device nil :defaults pn)))

That seems like a more useful arrangement than if DIRECTORY-NAMESTRING
is (b) and you need Windows-specific (and, unfortunately,
implementation-specific) code for (a), don't you think?

Finally, note that

  (lambda (pn)
    (namestring
     (make-pathname :name nil :type nil :version nil
                    :defaults pn)))

might conformingly produce a string containing a host, e.g.,
"localhost:Z:\\foo\\". So NAMESTRING isn't necessarily an ideal tool for
doing (a) or (b). I suspect that's why DIRECTORY-NAMESTRING and
FILE-NAMESTRING exist at all.

Regards,
Richard

P.S., In fact, I believe the phrase, "the directory name portion" got
into ANSI via a couple editing mistakes a few years apart. In CLtL,
DIRECTORY-NAMESTRING was defined as [1]:

  ... the result of DIRECTORY-NAMESTRING represents just the
  /directory-name/ portion; ...

That is, /directory-name/ was a hyphenated & italicized token, seemingly
intended as a defined term. But CLtL doesn't define it, and so, I guess,
some X3J13 editor de-jargonized it into two words in normal font.

Can we say what /directory-name/ might have meant as jargon? I think so:
the first two drafts of CLtL (Swiss Cheese, Aug 1981 [2] & Flat Iron,
Feb 1982 [3]) didn't have pathnames, but instead had Maclisp's namelist
representation for file names. A namelist had this structure (see page
238 in Swiss Cheese, or 248 in Flat Iron):

  ((host-name . directory-name) . file-name)

That is, /host-name/, /directory-name/, and /file-name/ are fields in
the namelist representation; and HOST-NAMESTRING, DIRECTORY-NAMESTRING,
and FILE-NAMESTRING were defined in terms of those fields in those
drafts. So DIRECTORY-NAMESTRING's original definition in Common Lisp
called for including the device in the string (when one was not missing;
namelists had a counterpart of NIL pathname component values).

Pathnames got into Common Lisp in the Colander draft (Jul
1982 [4]). Namelists were dropped, but DIRECTORY-NAMESTRING's definition was
not updated to use concepts in the pathname model, though
FILE-NAMESTRING's definition was. But nothing about the switchover from
namelists to pathnames compelled a change to the information included in
DIRECTORY-NAMESTRING's result: a roughly contemporaneous LispM manual
(1984) defines DIRECTORY-NAMESTRING as [5]:

  Returns a string showing just the device and directory of PATHNAME.

So I guess people who worked on CLtL either didn't notice the stray
undefined italicized jargon, or perhaps felt that some vagueness made
whatever their implementations already did legal, and left CLtL that
way. But I don't think DIRECTORY-NAMESTRING was intended to contain only
the directory component, though as I said above, I see how that's a
valid interpretation of how ANSI ended up.

[1] https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node214.html#SECTION002716000000000000000

[2] https://www.softwarepreservation.org/projects/LISP/common_lisp_family/cmu/Steele-CLRM-Swiss_Cheese-Aug_1981-Annotated.pdf

[3] https://www.softwarepreservation.org/projects/LISP/common_lisp_family/cmu/Steele-CLRM-Flat_Iron-Feb_1982-Annotated.pdf

[4] https://www.softwarepreservation.org/projects/LISP/common_lisp_family/cmu/Steele-CLRM-Colander-Jul_1982.pdf

[5] https://github.com/hanshuebner/lmman/blob/1bfe47e4cb47527558a42383ada01ff66b2ddb6b/pathnm.xml#L930


_______________________________________________
Sbcl-help mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-help