Re: Naive DEFSYSTEM replacement

"Robert Goldman (as rpgoldman at sift dot net)" <[email protected]>
Newsgroups gmane.lisp.lispworks.general
Message-ID <[email protected]>
On 27 Jul 2025, at 20:27, Adam Weaver wrote:

> I still don't really get UIOP though. Sure, there are inconsistencies
> between implementations (vagaries in the standard?) but Peter Seibel
> wrote a 100-odd-line shim FAD for his textbook to paper over the
> PATHNAME differences.

I don't mean to disparage Peter, but CL-FAD is much less ambitious, and 
really is not fit for purpose.  Consider, for example:

```
(defun directory-pathname-p (pathspec)
   "Returns NIL if PATHSPEC \(a pathname designator) does not designate
a directory, PATHSPEC otherwise.  It is irrelevant whether file or
directory designated by PATHSPEC does actually exist."
   (and
     (not (component-present-p (pathname-name pathspec)))
     (not (component-present-p (pathname-type pathspec)))
     pathspec))
```

Note that this simply looks at the syntactic form of the pathname.  Note 
also that (as far as I can tell!) there is no part of the spec to tell 
us what the form of a directory pathname should be.  Peter has to assume 
that it is something that has `NIL` or `:unspecific` in its name and 
type properties.  There is no obligation for a lisp implementation to 
abide by Peter's intuitions.

Now compare this with what Fare did to make a reliable, portable version 
of `probe-file` that returns the absolute pathname of a file:

```
   (defun probe-file* (p &key truename)
     "when given a pathname P (designated by a string as per 
PARSE-NAMESTRING),
probes the filesystem for a file or directory with given pathname.
If it exists, return its truename if TRUENAME is true,
or the original (parsed) pathname if it is false (the default)."
     (values
      (ignore-errors
       (setf p (funcall 'ensure-pathname p
                        :namestring :lisp
                        :ensure-physical t
                        :ensure-absolute t :defaults 
'get-pathname-defaults
                        :want-non-wild t
                        :on-error nil))
       (when p
         #+allegro
         (probe-file p :follow-symlinks truename)
         #+gcl
         (if truename
             (truename* p)
             (let ((kind (car (si::stat p))))
               (when (eq kind :link)
                 (setf kind (ignore-errors (car (si::stat (truename* 
p))))))
               (ecase kind
                 ((nil) nil)
                 ((:file :link)
                  (cond
                    ((file-pathname-p p) p)
                    ((directory-pathname-p p)
                     (subpathname p (car (last (pathname-directory 
p)))))))
                 (:directory (ensure-directory-pathname p)))))
         #+clisp
         #.(let* ((fs (or #-os-windows (find-symbol* '#:file-stat :posix 
nil)))
                  (pp (find-symbol* '#:probe-pathname :ext nil)))
             `(if truename
                  ,(if pp
                       `(values (,pp p))
                       '(or (truename* p)
                         (truename* (ignore-errors 
(ensure-directory-pathname p)))))
                  ,(cond
                     (fs `(and (,fs p) p))
                     (pp `(nth-value 1 (,pp p)))
                     (t '(or (and (truename* p) p)
                          (if-let (d (ensure-directory-pathname p))
                           (and (truename* d) d)))))))
         #-(or allegro clisp gcl)
         (if truename
             (probe-file p)
             (and
              #+(or cmucl scl) (unix:unix-stat (ext:unix-namestring p))
              #+(and lispworks os-unix) (system:get-file-stat p)
              #+sbcl (sb-unix:unix-stat (sb-ext:native-namestring p))
              #-(or cmucl (and lispworks os-unix) sbcl scl) 
(file-write-date p)
              p))))))
```

If you want to have a portable system definition facility like ASDF, you 
simply can't do without this kind of thing.  It would be lovely if we 
could get the implementation maintainers to agree on a more robust 
portable approach to accessing the filesystem and build it themselves, 
but that is not the world we live in.

To be honest, I can't imagine anyone but Fare who would have had the 
patience and determination to do all this and get it right.  There's 
some stuff in UIOP that is not strictly speaking critical to ASDF's 
function, but much less than you might think.  When you need to do 
something like figure out what files need loading, you need robust 
access to the filesystem.  The CL spec does not provide that. CL-FAD 
does not either. In a lot of cases Peter made some guesses about the 
meaning of pathnames, and they *mostly* work. But "mostly" isn't good 
enough for ASDF.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.