Older blog entries for crhodes (starting at number 69)

In the interests of more screenshots, here's an example of what one can do in a real Lisp application. Full disclosure: all of the layers of software above glibc (sbcl, McCLIM and gsharp itself) have version numbers below 1.0 — so don't be too surprised that it doesn't display the second beam of the semiquavers...

Consider the engraving of a piece of music such as Dvořák's Humoresque. You know the one: ‘dum-de dum-de dum-de dum-de dum-de dum-de dum-de dum-de dum-de dum-de dum-de dum-de daaaaah’. Well, typing this in in a linear fashion is an absolute pain; the engraver must change the input state between each note, or must modify each note after placing it.

What are computers for? Well, one would hope that at least one could use them to automate repetitive tasks. Emacs, for one, has keyboard macros for just this. So, first enter the notes, then C-x ( ] . C-f [ [ C-f C-x ) defines a keyboard macro for turning crotchets into real rhythm, and C-x e executes it. Apply a liberal dash of barlines, and voilà! Kudos to Robert Strandh for a neat patch (and, let's face it, for writing most of gsharp and a fair bit of McCLIM in the first place). One could also imagine writing a specialized function to alter the input state in the desired fashion automatically; that wouldn't be hard either, I think; but this is already a good feature to have.

Some bugs are more fun than others.

<Kryztof>   could be a ppc backend bug                                21:16:47
<antifuchs> what's the difference that makes the ppc act up on that?  21:16:56

So apart from demonstrating my latent psychic abilities, this bug was responsible for quite some head-scratching:

(iter (for i in '(1 2 3)) (+ i 50))
  => NIL ; on x86 and sparc
  => ERROR "2 is not a LIST" ; on ppc

Eventually, though, I tracked it down (:TRACE-FILE as an option to COMPILE-FILE is a wonderful thing), and it was amusing. The distilled test case I came up with was as follows

(defun foo () (values 1 2 3 4 5 6 7))
(defun bar (fn)
  (let (aa bb cc dd ee ff gg hh)
    (multiple-value-bind (a b c d e f g h)
        (funcall fn)
      (setq aa a)
      (setq bb b)
      (setq cc c)
      (setq dd d)
      (setq ee e)
      (setq ff f)
      (setq gg g)
      (setq hh h))
    (values aa bb cc dd ee ff gg hh)))
(assert (null (nth 7 (bar #'foo))))

So what's going on here? Well, the relevant piece of information here is that since calling FOO only returns seven values, the 8th (or, counting from zero, the 7th) should default to NIL. So that's what the ASSERT is doing; what's going wrong? To answer that, it helps to know that Gary Byers based his PPC backend of CMUCL (from which SBCL liberally borrowed) on the already-existing SPARC backend. However, the SPARC instruction set architecture has branch delay slots, such that the instruction following a branch is executed whether the branch is taken or not; the PPC has no such thing. So the cleverly-optimized loop for defaulting unknown values in the SPARC backend, when transcribed into PPC, doesn't work nearly so well...

Latest new toy: gsharp. The first surprise is that it's a Lisp application that looks, well, nice. OK, nice-ish. It's version 0.2, it has time to improve.

The second surprise was that the current CVS is noticeably more responsive than the version I'd been reading and playing with. I like it when things like that happen.

So, in any case, there are plenty of things missing, but I think it has potential. Let's get hacking!

(This cringe-inducingly upbeat tone will not last, I promise. Normal behaviour will resume shortly)

As an introduction to this entry, I should perhaps point out that writing papers is not a completely foreign craft to me; as part of my PhD, I have written a number of articles for peer-reviewed journals (and had my name added to a couple more...), so it's not a new thing. Also, I hope that this will continue — my academic career will be fairly short if I find myself unable to get anything anything else past referees.

However, it's unlikely that an article on the use of read-time conditionals in Common Lisp will interest the journals with which I'm most familiar; and if I am honest I don't think that the article in question is really journal material: it's simply a collection of anecdotes, arranged to tell a story with a moral. Also, at least certain publishers show a decided lack of enthusiasm about the subject matter, though fortunately other publishers would appear to be less reticent. So, anyway, it's probably better all round if I simply make it available to interested parties and leave it at that.

So, you heard it here first, probably: Maintaining Portable Lisp Programs, a study of how *features* can become bugs.

Others have written about what Common Lisp's logical pathnames (sic) are good for, and what not: the short version is that they are not intended for accessing or even describing files not under the control of the Lisp program.

However, we still have to implement the damn things. So here's an entertaining question: what does

  (directory "FOO:DEFSYSTEM.*")
mean, given that (logical-pathname-translations "FOO") returns
(("**;*.LISP" "/usr/share/common-lisp/source/**/*.lisp")
 ("**;*.FASL" "/usr/lib/common-lisp/**/*.lisp"))
? Naïve implementations of directory will throw an error, because they will attempt to translate (in the translate-logical-pathname sense) a logical pathname for which no translation exists. I would advocate a different interpretation: that all possible pathnames matching the queried one should be translated, and the resulting physical queries carried out.

In practice, this requires computing the intersection of two wild pathnames (in the example above, "FOO:DEFSYSTEM.*" and "FOO:**;*.LISP", for instance, which clearly have an intersection of "FOO:DEFSYSTEM.LISP"). This turns out, somewhat surprisingly, to be an immensely difficult operation to express — it took me over 100 lines of Lisp, and I'm still not confident that it's doing the right thing even for a relatively limited, though common, subset of pathnames.

But what sweet joy it is to be able to do (directory "SYS:*;") and have SBCL return (#P"/home/csr21/sourceforge-cvs/sbcl/contrib/" #P"/home/csr21/sourceforge-cvs/sbcl/src/").

We did quite well for last year.

Yesterday, after meeting Oxford physics people during the day to discuss moving forward on our projects, I met Dan for dinner, and the 2003 SBCL (UK branch) AGM. Two is quorate, yes.

So, let's see:

  • Native threads: check.
  • Better, faster, more integrated CLOS: check.
  • GenGC on non-x86: partly done.
  • Contributed modules infrastructure: check.
  • More ports: check.
  • Linkage Tables: partly done.
  • State of the Implementation: oops.
  • XREF: sort of.
which isn't a bad strike rate considering the various other things that happen in people's lives. As for this year, well, 64-bit will probably happen; some form of Unicode support will probably happen; I will write up some of the stuff that's important; and I hope that we'll release that dream of software writers: version 1.0.

ANSI saith:

Using :absolute or :wild-inferiors immediately followed by :up or :back signals an error of type file-error.
As we have discovered, we need an Oracle (no relation) to interpret this mystifying pronouncement. What it would appear to mean is that at some point between creating a pathname with such a deviant directory structure and attempting to use it to discover something about the filesystem using standardized operators, a conforming Common Lisp should signal an error.

So far, so good. However, as the n+1th evidence of a severe mismatch between the Common Lisp "portable" pathname standard and any kind of Unix, it should be pointed out that the pathname named by "/../" (that is, in Lisp terms, (:absolute :up)) has well-defined semantics.

In practice, this means that I'm extremely reluctant to detect this error early (as might otherwise be the good citizen implementation); I don't want to throw an error from MAKE-PATHNAME or MERGE-PATHNAMES, because pathnames made this way could still be useful, albeit not through the standardized operators. In particular, feeding one of these deviant pathnames to SBCL's POSIX interface layer is a perfectly valid thing to do, and I think I want to support that.

So instead, we have to detect accesses to the filesystem of one of these pathnames. Which is, of course, harder, but fortunately for my sanity (working with CL pathnames sucks) not all that hard — it only touches three different places in the code rather than one. To whomever implemented the first version of CMUCL pathnames: thank you.

So today I decided that we probably ought to move forward rather than be stuck through forces beyond our control, so I kludged around the GC problems. SBCL CVS HEAD should now be roughly well-behaved, and certainly shouldn't be so laughably fragile as it has been for the last week.

This will unblock some of my current work, such as improving the performance of SBCL on various benchmarks, and a better interface for compile-time customization of diagnostic messages. I hope it also unblocks other people's stuff, but it's been quiet (though not silent, fortunately) recently.

There are a couple of other things I feel I should comment on. Firstly, Edi Weitz has ported ASDF-INSTALL (briefly: a lisp tool for downloading "third-party" libraries) to a bunch of other (i.e. not SBCL) Lisps. As a lisp programmer, this has to be a good thing, because it means the constant whiners about lisp being hard get one more rebuttal... of course, I'm slightly disappointed that one of SBCL's killer advantages is no longer so clear.

The other thing is the notion that there is no "good" free Lisp (by which here I mean Common Lisp). I'm not sure, but I think perceptions are skewed, maybe by something like the Moon on a Stick phenomenon: people seem to accept problems in software they've paid for much more readily than in things they haven't — or, rather, I think they make an implicit calculation based on cost of the value of incremental improvements.

Maybe I should just sell SBCL for $200 a throw, or somesuch. It would be nice, if buyers could be found...

10 Jan 2004 (updated 12 Jan 2004 at 17:38 UTC) »

First, I started doing this diary weblog thing, and it was good. Nobody much noticed what I was doing, but it warmed my ego, and gave me a place to note little things that I discovered. Then I noticed that it seemed to be taking off; what was more surprising to me at the time was that they seemed to be being read.

Now, I'm actively being sought out, along with a number of people (well, online presences) with aligned interests. My wisdom is now being disseminated to a wider world out there. I'd better be more careful what I say.

(The irony of a diary entry free of Lisp content, discussing a Lisp diary aggregator, is not lost on me).

8 Jan 2004 (updated 8 Jan 2004 at 13:31 UTC) »

Aargh.

I spend time fighting SourceForge's Compile Farm (actually, I have few complaints about this aspect of their service; I think I'm getting more than I pay for) to build two different versions of SBCL for MacOS X, so that I can investigate the problems of RUN-PROGRAM on the PPC.

However, I can't reproduce the problem. At all. No matter how hard I try, all my RUN-PROGRAMs work fine.

<chandler> Krystof: is the machine you're trying to duplicate it on a dual-processor machine?
<chandler> Krystof: if so, you won't be able to

So. How annoying. SourceForge's Compile Farm machines are clearly too good...

60 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!