$ clisp --version
GNU CLISP 2.49 (2010-07-07) (built 3519331083) (memory 3519302729)
Software: GNU C 4.4.5
gcc -O2 -march=core2 -fomit-frame-pointer -pipe -Wa,--noexecstack -W -Wswitch -Wcomment -Wpointer-arith -Wimplicit -Wreturn-type -Wmissing-declarations -Wno-sign-compare -Wno-format-nonliteral -O -falign-functions=4 -DENABLE_UNICODE -DDYNAMIC_FFI -I. -Wl,-O1 -Wl,--as-needed /usr/lib64/libreadline.so -lncurses -ldl /usr/lib64/libavcall.a /usr/lib64/libcallback.a -L/usr/lib64 -lsigsegv -L/usr/lib64 -lc libgnu_cl.a
SAFETY=0 TYPECODES WIDE_HARD GENERATIONAL_GC SPVW_BLOCKS SPVW_MIXED TRIVIALMAP_MEMORY
libsigsegv 2.8
libreadline 6.1
Features:
(READLINE REGEXP SYSCALLS I18N LOOP COMPILER CLOS MOP CLISP ANSI-CL COMMON-LISP
LISP=CL INTERPRETER SOCKETS GENERIC-STREAMS LOGICAL-PATHNAMES SCREEN FFI
GETTEXT UNICODE BASE-CHAR=CHARACTER WORD-SIZE=64 PC386 UNIX)
C Modules: (clisp i18n syscalls regexp readline)
Installation directory: /usr/lib64/clisp-2.49/
User language: ENGLISH
Machine: X86_64 (X86_64) localhost [127.0.0.1]
The problem:
probe-pathname sets the version field to :NEWEST, and so this pathname is never EQUAL to another one returned by PATHNAME.
(pathname-version (probe-pathname "/tmp/"))
:NEWEST ; this should be NIL
(equal (probe-pathname "/tmp/") (pathname "/tmp/"))
NIL
Furthermore, MAKE-PATHNAME does not initializes the VERSION slot in the following case:
(defparameter *path* (probe-pathname "/tmp/"))
*PATH*
(pathname-version (make-pathname :version NIL :defaults *path*))
:NEWEST ; this should be NIL
This workaround can be done, but this is ugly:
(pathname-version (make-pathname :version NIL :name (pathname-name *path*) :defaults *path*))
NIL
Unfortunately, there is even more related bugs like this.
(length (directory "/tmp/*/"))
13
(length (directory "/tmp/*"))
7
So my /tmp directory has files and directories too, then:
(pathname-version (car (directory "/tmp/*/")))
NIL ; correct
(pathname-version (car (directory "/tmp/*")))
:NEWEST ; should be NIL!
But the file pathname creation seems to be good
(pathname-version (pathname "does-not-exist.dne"))
NIL
Furthermore,
(pathname-version (pathname "/tmp/"))
NIL ; ok
(pathname-version (pathname "dir/"))
NIL ; ok
(pathname-version (pathname "file"))
NIL ; ok
(pathname-version (merge-pathnames "dir/" "/tmp/"))
:NEWEST ; should be NIL!
(pathname-version (merge-pathnames "file" "/tmp/"))
:NEWEST ; should be NIL!
This bug report is now marked as "pending"/"invalid".
This means that we think that the problem you report is not a problem with CLISP.
Unless you - the reporter - act within 2 weeks, the bug will be permanently closed.
Sorry about the inconvenience - we hope your silence means that you agree that this is not a bug in CLISP.
http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/fun_merge-pathnames.html
default-version---a valid pathname version. The default is :newest
i.e., whenever pathnames are merged without an explicit default-version argument,
the result will have the :newest version unless the original pathnames have non-trivial versions
which is unlikely because no modern filesystem has a notion of a version built-in.
i.e., the behavior you are complaining about is mandated by the standard.
moreover, it is at least somewhat useful because it lets you know whether the pathname is a result of a merge with *default-pathname-defaults* or of raw parsing.
I see your point, but I think there are still problems.
Problem #1:
http://www.lispworks.com/documentation/HyperSpec/Body/f_merge_.htm
The standard says: "If pathname does not specify a name, then the version, if not provided, will come from default-pathname, just like the other components."
(pathname-version (merge-pathnames "dir/" "/tmp/"))
:NEWEST ; so this should be NIL
as fortunately
(pathname-version "/tmp/")
NIL
Problem #2:
(pathname-version (probe-pathname "/tmp/file"))
NIL
(pathname-version (probe-pathname "/tmp/dir/"))
NIL
(pathname-version (probe-pathname "/tmp/"))
:NEWEST ; should be NIL
I think CLISP should be consistent here. Why does it return :NEWEST in the last case?
Problem #3:
(pathname-version (car (directory "/tmp/*/")))
NIL
(pathname-version (car (directory "/tmp/*")))
:NEWEST
Is there any way to let CLISP's directory function return NIL in this last case?
Otherwise I have to convert all the file pathnames if I want consistency.
Eg, I want to compare pathnames with the equal function.
1. set *parse-namestring-ansi* to T so that symbols are not treated as pathname designators.
in your case when (probe-pathname "nonexistent") returns NIL, pathname-version converts it to a pathname with NIL version. see <http://clisp.org/impnotes/filename-misc.html#parsename>
2. from what I can see, clisp always returns :newest for versions of truenames. I don't see any problems with that.
1. set *parse-namestring-ansi* to T so that symbols are not treated as pathname designators.
in your case when (probe-pathname "nonexistent") returns NIL, pathname-version converts it to a pathname with NIL version. see <http://clisp.org/impnotes/filename-misc.html#parsename>
2. from what I can see, clisp always returns :newest for versions of truenames. I don't see any problems with that.
The problem with this behaviour is that you cannot compare pathnames with the equalp function.
I would like to get T for this:
(equalp (pathname "/bin/tr") (car (directory "/bin/*")))
NIL
where
(car (directory "/bin/*"))
#P"/bin/tr"
Setting the custom:*parse-namestring-ansi* didn't changed anything.
(pathname-version (probe-pathname "/bin/tr"))
:NEWEST
So some of the pathname handling functions set version to NIL, some of them set it to :NEWEST. This is what I call inconsistency.
(equalp (pathname "/bin/tr") (car (directory "/bin/*")))
is wrong because you are comparing "parsed pathname" with a "filesystem pathname".
you should try
(equalp (merge-pathname (pathname "/bin/tr")) (car (directory "/bin/*")))
:newest appears whenever pathnames are merged (without the default-version argument).
this is reasonable, compliant, and useful in some situations.
custom:*parse-namestring-ansi* does a very specific thing only tangentially related to your question.
Hm, I never thought of using MERGE-PATHNAMES with one argument.
It works indeed for file names. But it seems to fail for directory names.
So if
(car (directory "/tmp/*/"))
#P"/tmp/swtlib-64/"
Then
(equalp (merge-pathnames (pathname "/tmp/swtlib-64/")) (car (directory "/tmp/*/")))
NIL
It happens because MERGE-PATHNAMES _always_ set version to :NEWEST, but DIRECTORY sets the :NEWEST flag only to files. In case of directories, DIRECTORY sets NIL version.
This doesn't seem to be good. I think there should be an easy way to compare pathnames regardless whether they are file or directory pathnames.
- - - - - - - - - -
It is also interesting (as I pointed this out before) that CLISP does not follow the standard in the case below:
(pathname-version (pathname "/tmp/"))
NIL
(pathname-version (merge-pathnames "swtlib-64/" (pathname "/tmp/")))
:NEWEST
But the standard says: "If pathname does not specify a name, then the version, if not provided, will come from default-pathname, just like the other components."
See: http://www.lispworks.com/documentation/HyperSpec/Body/f_merge_.htm
So as
(pathname-name (pathname "/tmp/"))
NIL
the MERGE-PATHNAMES call above should set NIL version instead of :NEWEST.
ok, now all the truenames have non-nil version
thank you for your bug report.
the bug has been fixed in the source tree (mercurial/hg).
you can either wait for the next release (recommended)
or check out the current mercurial tree (see http://clisp.org\)
and build CLISP from the sources (be advised that between
releases the source tree is very unstable and may not even build
on your platform).