Subject: Re: bug#12351: 24.1; parse-colon-path turns empty paths into nil

From: Dave Abrahams <[email-masked]>
Date: Sun, 30 Dec 2012 15:37:16 -0500

on Sun Dec 30 2012, Eli Zaretskii <eliz-AT-gnu.org> wrote:

>> From: Dave Abrahams <[email-masked]>
>> Date: Sun, 30 Dec 2012 14:53:44 -0500
>> Cc: [email-masked]
>> 
>> > Obviously we need the nils to remain, so I will put them back and just
>> > mention that empty elements return nil. It's not worth handling the
>> > minor aesthetic annoyance of (nil nil) specially.
>> 
>> FWIW, I disagree. IMO you should at least consider fixing eshell and any
>> other things that break because of this change.  This discontinuity in
>> behavior is not merely aesthetic; it makes parse-colon-path difficult to
>> use correctly and leads to hard-to-find bugs in any code that fails to
>> account for the possible nils.
>
> This whole discussion is rather futile, unless the opinions are also
> backed up by real-life use cases.  Can you tell why the previous
> behavior made parse-colon-path difficult to use, and in what
> situations?

Instead of recording that complex situation when I encountered the bug I
helpfully (!) recorded a reduced reproducible example that stripped away
the use case, which I didn't remember... but I even went the extra mile
to reconstruct it.  For example, look at 

http://edward.oconnor.cx/elisp/osx-plist.el

The following function is buggy because of the original bug:

--8<---------------cut here---------------start------------->8---
(defun osx-plist-update-exec-path ()
  "Update `exec-path' from the PATH environment variable."
  (let ((path (getenv "PATH")))
    (mapc (lambda (dir)
            (add-to-list 'exec-path dir))
          (parse-colon-path path)))
  exec-path)
--8<---------------cut here---------------end--------------->8---

I had to replace it in my local installation as follows:

--8<---------------cut here---------------start------------->8---
  (defun osx-plist-update-exec-path ()
    "Update `exec-path' from the PATH environment variable."
    (let ((path (delq nil (parse-colon-path (getenv "PATH")))))
      (setq exec-path
            (dolist (dir exec-path path)
              (add-to-list 'path (file-name-as-directory dir) :append)))))
--8<---------------cut here---------------end--------------->8---

If you go looking for instances of parse-colon-path I'm sure you'll find
hundreds of other places where the use was tailored to the documented
behavior of parse-colon-path rather than the specific oddball behavior
that was actually implemented.  I found at least one in my own code just
now.

IMO, though, you should actually be able to understand this one without
any examples.  Any discontinuity in behavior means the client needs to
write special-case code to handle that special-case behavior.  For one
or two clients it may be that the special-case behavior matches just
what they need, but in general that's highly unlikely.  Combine this
with the fact that the uniform behavior has been documented for years,
and that the inputs that trigger the non-uniformity are rare, and you
can be pretty confident that more code has been written to the uniform
specification.

-- 
Dave Abrahams
BoostPro Computing                  Software Development        Training
http://www.boostpro.com             Clang/LLVM/EDG Compilers  C++  Boost