opening it up with Common Lisp

Favorite weblogs

Lisp Related

Bill Clementson

Finding Lisp

Lemonodor

Lispmeister.com

Planet Lisp

Politics

Orcinus

Talking Points Memo

This Modern World

Working for Change

Other home

Polliblog

Recent Readings

Book review: Darwinia
Reviewed: Friday, August 11, 2006

Summer reading: Spin
Reviewed: Saturday, August 5, 2006

Runner
Reviewed: Tuesday, July 18, 2006

the Omnivoire's Delimma
Reviewed: Wednesday, July 12, 2006

the Golem's Eye
Reviewed: Wednesday, May 31, 2006





tinderbox
 width=

RDF Triples in XML
Sunday, August 20, 2006

(After all, where else would you put them?).

Even after everything is in RDF, you still need to find someplace to put it and a way to write it down. Big disks answers the first question but the second has turned out to be surprisingly hard. Since XML has become the one (markup language) to rule them all, it was no surprise that people turned to it for the answers. Unfortunately, dealing with everything has a way of pulling in competing constituencies and those pesky subgroups tend to pull things into a muddle. This left RDF/XML of several diverse forms each very successful but each with its own problems. This paper presents another way to look at stuff that, as far as I know, has gone on to become quite successful.


IT Conversations
Sunday, August 20, 2006

  • Tara Lemmey talks about US security in the age of "terror". If these ideas are actually implemented, then things might become better. My guess, however, is that we'll just have more technology without thought scares.
  • Ray Lane talks about software and stuff stream of consciousness style at Software 2006. His stream is moderately interesting.
  • Elias Torres talks about the Semantic Web (RDF, OIL, SPARQL, oh my!) with Phil Windley. Torres does a good job explaining why we care though I can't help but hear shades of the "AI will solve everything" from the early 80's whenever I hear about the Semantic Web.

more "real" C++ macros via template metaprogramming
Saturday, August 19, 2006

If it didn't end up being so ugly, it would be cute.

Although this technique might seem like just a cute C++ trick, it becomes powerful when combined with normal C++ code. In this hybrid approach, source code contains two programs: the normal C++ run-time program, and a template metaprogram which runs at compile time. Template metaprograms can generate useful code when interpreted by the compiler, such as a massively inlined algorithm -- that is, an implementation of an algorithm which works for a specific input size, and has its loops unrolled. This results in large speed increases for many applications.

This is from a longer article by Todd Veldhuizen referenced by Scott Meyers (it's on the web somewhere but I seem to have misplaced it ).

Someone should create a language that lets you do this without having to jump through so many hoops. It could work per taking source code as inputs and writing out new source code with the whole power of the language behind the transformations. A language like that would blow C++ out of the water in terms of popularity. What's that. Oh, sorry. I went off my meds again.


SPAM on the lam? Not for me!
Saturday, August 19, 2006

It used to be that most of my SPAM went into junk. Lately, however, a great deal of stuff that looks as if it should be easy to categorize is ending up in my inbox. Grrrr.

I'm guessing that I should try retraining my SPAM filter (in OS X's Apple Mail) or switch to something like Michael's Tsai's SpamSieve. I used SpamSieve once before and liked it -- but why pay when Apple Mail seemed to be doing as good (or at least nearly as good) of a job? Is anyone else experiencing this?


Feedback: good and bad
Friday, August 18, 2006

It's ironic I received both high praise and an indictment for my Lisp software on the same day! Both, however, were deserved. Well, I know I deserve the indictment and I'm pretty sure that the praise is justified too. First, I heard that CL-Markdown's new extensions mechanism

I was able to complete a project today, just in time, and leave for seven days of vacation tomorrow. This wouldn't have been possible in that form without markdown extensions...

That cheered me up. Later in the day, however, I heard that:

... most of the web pages for your various lisp packages need to be updated. You don't list nearly all of the required dependencies. ... I'm so annoyed from having to go through the discovery process that I'll let you discover which pages are inadequate.

Which is quite true. I suppose it would be sort of OK if I didn't list any dependencies but only listing some of them really opens the door for frustration. Besides, it's easy to pull all of this stuff and include it in the web pages automatically.

Things to do:

  • Switch from lml2 to CL-Markdown for my web site
  • Add CL-Markdown extensions to include the dependencies automatically
  • Improve the Enterprise Lisp system pages so that they list this stuff automatically too
  • Keep on keeping on.

Thanks for both the kind words and the less kind ones. I want Lisp to succeed and that's only going to happen if the barriers to entry become ever lower.


RIFE
Friday, August 18, 2006

I just heard about RIFE which sounds like RAILS only it's Java, etc... The nice thing is that Lispers could start working on LIFE which has gotta be good, right? The linked interview has an interesting comment differentiating Rails from RIFE:

Some people criticize RIFE for not being like Ruby on Rails, where you can just start coding and have something up and running.

...

Why? Because we've been bitten so many times by the maintainability issue. We think that declaring certain things beforehand makes your application easier to maintain—for instance, it forces you to think of how state is being managed in your application.


Update: CL-Markdown again
Monday, August 14, 2006

Thanks for Frank Schorr for noticing that CL-Markdown sometimes failed to produce output. Actually if it failed once, it never stopped failing but when it succeeded, it never failed. It was a file compilation order dependency problem that didn't occur in my usual development environment. I'd been thinking that having a system compile an ASDF system in every order allowed by the dependencies would be a good way to catch certain bugs... it would have caught this one (assuming that a lot of additional infrastructure was in place <smile>).

When, on when, will someone kick me in the butt so that I can get back to Enterprise Lisp? New files are up on Common-Lisp.net.


the Human Condition
Sunday, August 13, 2006

I like conditions. I like them a lot. I like to use them to describe bad program states instead of strings. (e.g., (assert (ok-p state) nil 'it-is-not-ok-condition :state state) instead of (assert (ok-p state) nil "It is not ok")). I like them because you can easily test whether or not they happened programmatically and because using them helps to centralize error messages -- and thus gives me hope that I can make them consistent. There is a catch though: define-condition is a prolix form. Thus Metatilities has long had defcondition to make writing them a bit easier and yesterday I wrote a sibling macro (with the same name) to handle my most common case. The macro is simplicity itself:

(defmacro defcondition (name (&rest super-conditions) 
			slot-specs format &body args)
  (flet ((massage-slot (slot-spec)
	   (cond ((atom slot-spec)
		  `(,slot-spec 
		    :initarg ,(read-from-string (format nil ":~a" slot-spec))))
		 (t
		  slot-spec)))
	 (massage-format-arg (arg)
	   (cond ((atom arg)
		  `(slot-value condition ',arg)) 
		 (t
		  arg))))
    `(progn
       (export '(,name))
       (define-condition ,name ,super-conditions
	 ,(mapcar #'massage-slot slot-specs)
	 (:report (lambda (condition stream)
		    (format stream ,format 
			    ,@(mapcar #'massage-format-arg args))))))))
  

and this lets us write

(define-condition record-number-too-large-error
    (invalid-record-number-error)
  ((record-count :initarg :record-count))
  (:report 
   (lambda (condition stream)
     (format stream 
	     "Record number ~a is too large for this store. Store size is ~a."
	     (slot-value condition 'record-number)
	     (slot-value condition 'record-count)))))

as

(defcondition record-number-too-large-error
    (invalid-record-number-error)
    (record-count)
    "Record number ~a is too large for this store. Store size is ~a."
  record-number record-count)

(the record-number slot is inherited). It's not much but its enough to make writing simple condition like this almost as easy as writing an error message as string. Programming environments are (in part) about reducing impedance and about making it easy to do the right thing.


Book review: Darwinia
Friday, August 11, 2006

I very much enjoyed Robert Charles Wilson's Spin and I was looking forward to reading Darwinia. I'm glad I read them in the order I did because I thought Spin was superb and Darwinia both trite and silly. The characters are well drawn and relationships matter but the central premise -- that earth (and the rest of the universe) is essentially a library book come to life and is rewriting itself because of the attack of computer viruses on steroids; that everything we know is composed of a vast cosmological battle between sentience and these viruses... well, it's an interesting idea.

Darwinia feels as if it could have been great but it isn't. It feels tacked together from several weaker ideas and grand notions and never quite evolves beyond itself. Oh well, you can't always write a masterpiece.


Update: CL-Markdown
Tuesday, August 8, 2006

I've corrected another few bugs in CL-Markdown and improved the extensions a bit.

  • Fixed error in the processing of multiple bracketed things (e.g., [a][b] and [c][d]).
  • Improved table of contents processing.

It actually works pretty well (I suppose I shouldn't be surprised! Smile)


:explain that :box, will you?
Tuesday, August 8, 2006

One of Common Lisp's darker arts is optimizing functions. It's a beautiful idea: don't worry (too much) about performance until you've found the critical sections of your code; then tell the compiler what you'd like and, voila, faster code. Since compilers differ, however, and since you're never quite sure what incantation is going to convince Lisp to do "the right thing" (*), you're often left flipping declarations around like hot potatoes.

Enter Allegro Common Lisp, version 8.0 I've been working lately (for money even!) in ACL and one of the wonderful new features is that you can ask the compiler to tell you what it thinks and what it wants. I've wanted this ability for a long time (I even talked about it at ILC 200? in NYC). Let the programming environment notice that such and such a function is suboptimal and tell me that if I scratch it's back (with a little more information), then it can scratch mine (with a little more performance). ACL's explain feature isn't quite that, but it's a great step in that direction.

(*) I.e., what you want it to. Joke.


Cellular signposts
Tuesday, August 8, 2006

I suffer from psoriasis (and it's not just a heartbreak!). One of the many interesting questions about this disease is why this little bit of skin is undergoing massive immune mediated wonkiness (MIMW) and this bit of skin next to it thinks that everything is normal. This article (which I found via the American Scientist) gives part of an explanation. Cool.


Perception, reality, etc.
Tuesday, August 8, 2006

Java, Python, Ruby guru Mark Watson points out that he feels more productive using LaTeX rather than Word and this reminds me of the whole "is incremental spell checking really a good thing" debate (that I've had with myself annually since 2003; don't be too surprised if you haven't heard about it; my ex-agent failed to get the big network contracts he promised. Which reminds me, isn't stream of consciousness interesting. I suppose it depends on the consciousness... <smile>).

At question is what work style and tools help humans find maximum productivity and creativity. Is is better for a writer to work with pencil and paper -- forced to produce marks on paper at a rate slower than thought -- or with a word processor that highlights spelling, grammar, and logical inconsistencies (I made that last one up) on the fly? Is it better for a programmer to submit batch jobs to a mainframe or have background processes constantly checking the source for problems? The truth is probably a muddy thing. My opinion, however, is that the best (in terms of productivity, creativity, and flow) is highly context dependent and is often at odds with what feels psychologically most productive.

We need time to think; we need (metaphorical) quiet to get into the flow. A tool that shouts "spelling error" with every typo is providing more distraction that help. Yet it feels good to make those red squiggles disappear -- "We're making progress!" -- it feels good to play with fonts and shift the format. A computer is a far different beast that Heidegger's hammer: it can be at hand in many ways simultaneously. It's up to us to ensure that the tools we use are optimizing the important tasks, not the trivial ones.


Summer reading: Spin
Saturday, August 5, 2006

I'm sure many of my readers are saying to themselves (quietly so as not to attract attention to themselves) "It's summer, why isn't Gary reading?". Well say no more, squire, say no more. I have been reading, I've just been keeping quiet about it.

Spin is a wonderful book by the novelist Robert Charles Wilson. Normally, I worry about people with multiple first names -- seems to me that it must leave them confused on some deep, deep level. Of course, I used to think that the group Tony Orlando and Dawn was composed of three people named "Tony," "Orlando," and "Dawn"... it made sense to me. Enough about my neuroses, however, let's talk about the book.

Spin is science fiction in the best sense -- interesting science (yes) and interesting fiction (of course) but the heart of the book is the characters; not the plot nor the gizmos. The "spin" is an event caused by forces unknown for reasons unknown that leaves the earth wrapped in a shell. The stars and moon are no longer visible and satellite communication is impossible. The sun, however, still appears to rise and give warmth. Life goes on. Eventually, it's discovered that time on earth is moving more slowly than that of the universe outside the shell; much more slowly. Weeks on earth correspond to millennia. This means that the sun will consume its supply of hydrogen fuel, enter senescence and grow to consume the earth in less than a century. But why wrap the earth at all? Who is doing this? Is it the end of the world? Is it the rapture?

The book tracks the responses of three friends and the rest of the world to these questions. Wilson writes elegantly and eloquently; beautiful and at times heart rending phrases enliven the interplay of plot and character. In the end, science matters less than people and the hardest gap to cross is not the one between the stars but the one between self and other and, sometimes even less permeable, that between self and self.

Highly recommended for enjoyable science, wonderful writing and beautiful story.


Functional programming fun from Joel
Tuesday, August 1, 2006

Joel Spolsky writes well. He writes like a fish swims. Though not as glib as Paul Graham he still leaves an earnest yet unctuous film around the eyeballs and a bit of a grin around the mouth. In any case, he provides a great lead in for why MapReduce is way cool.


CL-Markdown extensions - first steps
Tuesday, August 1, 2006

I've made a little time to push on the CL-Markdown extension mechanism I wrote about a week or two ago. I've added a few new glitches but the change was less painful that I thought it might be (CL-Markdown swings far towards the organic and messy side of the code I write!)

In any case, the text below (written in Markdown format and parsed by CL-Markdown) describes how to write and use CL-Markdown extensions. The output isn't perfect (there are some glitches with quotations marks in code blocks for one thing), but it's pretty darn good if you ask me... (I know, biased, biased, biased... just like that SCLM). Let me know what you think!

CL-Markdown extensions

CL-Markdown aims to mirror the syntax of John Gruber's Markdown language (and it's getting there slowly!).

the Syntax

CL-Markdown uses { and } as new syntax markers. A single pair of curly braces wraps a function call whereas a double pair denotes a sort of wiki-like link. A function calls looks like:

\{function-name [function-argument]*\}

a wiki-like-link looks like

\{\{ syntax as yet to be determined \}\}

Function calls: { and }

Calling extension functions requires three things:

  1. writing (or finding) the extension that you want
  2. telling CL-Markdown that you want to use the extension
  3. writing your Markdown text with calls to the extension

The last part is the easiest; all you need to do is open a curly brace, type the name of extension function, type in the arguments (separated by spaces) and type a closing curly brace. For example:

"{now}" will generate the text "12:23".

The second step is necessary because CL-Markdown won't recognize functions as functions unless you tell it to up front. After all, you wouldn't want to allow people to execute arbitrary code; it might be a security risk (smile). Because CL-Markdown operates in two stages, there are two times when functions can be called: during parsing and during rendering. Functions active during these stages are keep in the special variables *render-active-functions* and *parse-active-functions*.

An example maight make this clearer. First, we'll call Markdown without specifying any functions:

? (markdown "Today is {today}. It is {now}." 
  :format :html :stream t)
<P>
Today is 
; Warning: Inactive or undefined CL-Markdown function TODAY
; While executing: #
<STANDARD-METHOD RENDER-SPAN-TO-HTML ((EQL EVAL) T)>
. It is 
; Warning: Inactive or undefined CL-Markdown function NOW
; While executing: #
<STANDARD-METHOD RENDER-SPAN-TO-HTML ((EQL EVAL) T)>
. 
</P>

As you can see, the functions weren't ones that Cl-Markdown was ready to recognize, so we got warnings and no text was generated. If we tell CL-Markdown that today and now should be treated as functions, then we see a far prettier picture:

? (let ((*render-active-functions* 
         (append '(today now) *render-active-functions*)))
    (markdown "Today is {today}. It is {now}." 
        :format :html :stream t))
<P>
Today is 1 August 2006. It is 11:36. 
</P>

By now, we've seen how to include function calls in CL-Markdown documents and how to generate those documents with CL-Markdown. The final piece of the puzzle is actually writing the extensions.

Writing Cl-Markdown extensions

There are several ways to write Cl-Markdown extensions. The easiest is one is to write functions active during rendering that return the text that you wish to be included in the document. For example:

(defun today (phase arguments result)
  (declare (ignore phase arguments result))
  (format-date "%e %B %Y" (get-universal-time)))

The format-date command is part of metatilities; it returns a string of the date using the C library inspired date format. This string is placed in the document whereever the function call ({today}) is found.

Alternately, one can use the *output-stream* variable to insert more complicated text. This would look like:

(defun now (phase arguments result)
  (declare (ignore phase arguments result))
  (format *output-stream* "~a" 
    (format-date "%H:%M" (get-universal-time)))
  nil)

(Note that now returns nil so that the date isn't inserted twice!).

The other alternative is to use your function calls to alter the structure of the CL-Markdown document and then let Markdown deal with some or all of the rest. The anchor extension provides an example of this:

(defun anchor (phase &rest args)
  (ecase phase
    (:parse
     (let ((name (caar args))
           (title (cadar args)))
       (setf (item-at (link-info *current-document*) name)
             (make-instance 'link-info
               :id name :url (format nil "#~a" name) 
               :title (or title "")))))
    (:render (let ((name (caar args)))
               (format nil "
<a name='~a' id='~a'>
</a>
"
                       name name)))))

Anchor makes it easier to insert anchors into your document and to link to those anchors from elsewhere. It is active during both parsing and rendering. During the parsing phase, it uses it's arguments to determine the name and title of the link and places this into the current document's link information table. During rendering, it outputs the HTML needed to mark the link.

An even more complex example is the table-of-contents extension:

(defun table-of-contents (phase &rest args)
  (bind ((arg1 (ignore-errors
                (read-from-string (string-upcase 
                                   (first args)))))
         (arg2 (ignore-errors
                (parse-integer (second args))))
         (depth (and arg1 (eq arg1 :depth) arg2)))
    (ecase phase 
      (:parse
       (push (lambda (document)
               (add-anchors document :depth depth))
             (item-at-1 (properties *current-document*)
                        :cleanup-functions))
       nil) 
      (:render
       (bind ((headers (collect-elements
                        (chunks *current-document*)
                        :filter
                        (lambda (x) (header-p x :depth depth)))))
         (when headers
           (format *output-stream*
                   "
<div class='table-of-contents'>
")
           (iterate-elements
            headers
            (lambda (header)
              (bind (((index level text)
                      (item-at-1 (properties header) :anchor)))
                (format *output-stream* "
<a href='#~a' title='~a'>
"
                        (make-ref index level text)
                        (or text ""))
                (render-to-html header)
                (format *output-stream* "
</a>
"))))
           (format *output-stream* "
</div>
")))))))

Because we can't generate a table of contents until the entire document has been parsed, the table-of-contents extension adds a function to the cleanup-functions of the current document. Cleanup functions are called when parsing is complete. The add-anchors functions adds additional chunks to the document before each header (down to some fixed depth). These anchors can then be used by the rendering phase of the table-of-contents extension to link the headers to the sections in the document.


Update: ASDF-Binary-Locations
Tuesday, August 1, 2006

ASDF-Binary-Locations now has another way to customize output locations thanks to Erik Enge. Erik's patch recognizes that sometimes you want to specify output location based on who is currently using the machine. Thus we have the new variable: *include-per-user-information*.

When *centralize-lisp-binaries* is true this variable controls whether or not to customize the output directory based on the current user. It can be nil, t or a string. If it is nil (the default), then no additional information will be added to the output directory. If it is t, then the user's name (as taken from the return value of #'user-homedir-pathname) will be included into the centralized path (just before the lisp-implementation directory). Finally, if *include-per-user-information* is a string, then this string will be included in the output-directory.

Enjoy.


Links to things I thought were cool
Sunday, July 30, 2006

After all, isn't that what the web is all about?

  • This could be the start of something really great: "In simplest terms, a way to fund high-quality, original reporting, in any medium, through donations to a non-profit called NewAssignment.Net."

  • I'm not sure if this is a good use, but it's better than nothing... "One of [Alex Dragulescu's] more notable projects involved creating what he calls Spam Plants. He wrote algorithms that analyzed various text and data points of junk e-mail to produce "organic" images of plantlike structures that spontaneously grew based on incoming spam."

  • Search is almost always interesting: here is a roundup of several "new" ideas

Some CL-Markdown design questions for public review
Tuesday, July 18, 2006

I've been using Peter Seibel's Markup (see also here for a fork by Cyrus Harmon) lately for a project. If you've seen LaTeX then Markup will be familiar. The nicest thing about it is that Peter has made it really easy to extend the language with your own commands. It's also very well integrated with Lisp and with Peter's other tools. On the other hand, it's not Markdown. This means that Markup documents tend to look like documents with Markup and that there is no convenient round trip from Markup to HTML and back again. Now I'd like to be able to say that CL-Markdown provided Markdown's extremely readable syntax with Markup's cool customization but I can't. At least, not yet. Here then, are my thoughts on the matter. Please let me know if anything resonates positively or, perhaps even more importantly, negatively with you.

First, what do I want to support?

  • I'd like an easy to way to associate properties with a document and to use those properties later,
  • I'd like to add some Wiki-link syntax to make using Markdown in a Wiki a bit more natural,
  • I'd like to add simple customization so that one can define commands in Lisp and invoke those commands at well known points during document parsing and production, and
  • I'd like the syntax to seem natural so that it doesn't get too much in the way of normal writing and reading.

Second, what do I propose:

  • I'm intending to make #\{ and #\} special characters (you can always escape them if you need to use them for more pedestrian purposes). Stuff between a pair of curly braces will be treated as a Lisp function invocation where the first word denotes the function and the rest of the words denotes arguments. Here are some examples.

    • {table-of-contents} - add a table of contents (based on H1, H2, and so forth headings). If you only want to go down to H3, then use {table-of-contents :depth 3}.

    • {set-property document-name "general"} - sets a property. In this case, document-name would be a well defined property that controls the name of the output file. You can use {property name} to retreive already set properties.

    • {function document-system} - used to output documentation for the function named 'document-system (cf. Tinaa)

    All of these examples presuppose that I (or someone) has written commands to accept and process them. I think that this mechanism handles about 90% of what I want. The only missing bit is Wiki-links.

  • For Wiki-links, I'm thinking of using double brackets. E.g. {{Another page}} would like to "Another%20Page". But one also wants to be able to specify different text and I think something like {{Another page} different text} would do fine. The syntax starts to get a bit overloaded but I think that even {{Another Page} different text :title This leads to another page :class funky-link} would be fine.

I'm not sure when I'll get to this... Soon, I hope but let me know (gwking@metabang.com) when you see something I've missing. Thanks.


Runner
Tuesday, July 18, 2006

William C. Dietz's Runner is decent science fiction: decent plot, decent characters, decent technology, decent writing. Everything about the book was, well, decent. If it sounds as if I'm damning with faint praise it's because I am. This was a book I finished only because it's the sort of book I can read very fast. There was nothing particularly bad about it but also nothing particularly good. The characters were mostly believable but there was nothing organic about the. The writing was passable but surely not memorable (no phrase savoring here, move along). The plot was a standard "make a journey and pick up allies and enemies and learn things about yourself on the way" and the science was neither deeply explored nor central to the plot. Maybe you'll love it, but there are better books out there to read.


Update: trivial-shell
Monday, July 17, 2006

Trivial Shell now works with CMUCL. Thanks to Satyaki for the patch.


Logo Wiki / Code Wiki
Friday, July 14, 2006

(Via Paolo Amoroso) The Logo Wiki is a great example of a code wiki. It needs some better version control of the code (in case of mistakes and typos) and I'm not sure how it deals with spam, etc. Still, it's fun and it makes it really easy to get a feel for Logo itself -- it helps that one of Logo's was (is?) teaching programming and that the interface is primarily a turtle carrying a pen!

Paolo Amoroso mentions that a Lisp variant would be even cooler and he's right in a way. I'm not sure that the examples would be as fun though.


the Omnivoire's Delimma
Wednesday, July 12, 2006

Dreams of innocence are just that; they usually depend on a denial of reality that can be its own form of hubris.

I'll try to avoid the obvious food puns but Michael Pollan's the Omnivore's Dilemma is a rich dessert of elegant verbal treats, sweetened with thoughts both philosophical and political.

(Quoting local food advocate Joel Salitin) "It's all connected. This farm is more like an organism than a machine, and like any organism it has its proper scale. A mouse is the size of a mouse for a good reason, and a mouse that was the size of an elephant wouldn't do very well."

Pollan's four meals (the industrial, the agrarian, the organic and the gathered) clearly delineate some of our possible relationships with food; what's more, it's clear that the most common relationships are the worst for us and the health of our shared biosphere.

Our food system depends on consumers' not knowing much about it beyond the price disclosed by the checkout scanner. Cheapness and ignorance are mutually reinforcing. And it's a short way from not knowing who's at the other end of your food chain to not caring--to the carelessness of both producers and consumers.

This lack of knowledge -- and indeed the (apparent) strong desire of the powers that be to deny knowledge, crush and impede the Freedom of Information Act, pretend that processed food is just like its real counterparts, distract us with (wonder) bread and circuses, and with fear -- is what worries me. I believe that people will do the right thing (most of the time, by and large) if they know what that thing is and if it's not too hard to do it and if doing it is visible and engenders positive feedback loops. Mass industrial capitalism does not support a human economy of scale.

Regardless of that, however, this is a great book and I enjoyed every minute of my reading!


Update: ASDF-Binary-Locations
Wednesday, July 12, 2006

Thanks to Joshua Moody, ASDF-Binary-Locations now knows something about 64-bit Allegro Common Lisp.


Update: CL-Markdown
Wednesday, July 12, 2006

I've made several small tweaks to CL-Markdown in an effort to bring it a bit closer to its Perl cousin. In particular:

  • I finally began to add to support for escaped characters (e.g., you can now say \*hello\* to output *hello*).
  • Corrected a few edge cases and missing bits of support for links
  • Many some very small improvements in the handling of Markdown coding with code blocks (it's not complete, but every step is a step).

As usual, CL-Markdown has a host of dependencies. You may want to try System-check to see what needs to be updated.


Mark Watson on Global Warming
Saturday, July 8, 2006

Lisp and Java consultant Mark Watson on global warming:

BTW, the solution to global warming (or at least improve the situation) is simple: increase the tax on the use of carbon based fuels while decreasing sales and income taxes. Make it economically viable to create new technologies and industries that reduce our energy and environmental damage "foot prints".

He's right. But America is addicted to oil, air conditioning and cheap corn so we know it won't happen.


Another step towards ASDF system understanding
Thursday, July 6, 2006

As usual, progress is slower than desired or expected and my reach seems to ever exceed my grasp (I think it has something to do with the anatomy of my hand...). Nonetheless, there are now some spiffy system dependency graphs up at enterpriselisp.com. Not surprisingly, CL-PPCRE's is one of the most complex. In case it's not clear (and it probably isn't!), you can navigate between systems by clicking on the graph vertexes. Also, the graphics are all SVG so you'll need a browser that knows how to speak it. More web phun is in the pipeline.


ASDF turns 100
Wednesday, July 5, 2006

I just had the honor of checking in the 100th revision of ASDF. Cool!

The newest feature is the addition of load-preferences and preference-file-for-system/operation. These generic functions can be specialized on the system and the operation.

The out of the box behavior of load-preferences is to do nothing except in the case of a load-op or a load-source-op. For either of those operations, load-preferences calls preference-file-for-system/operation to get a pathname. If the pathname returned exists, load-preferences loads it.

By default, preference-file-for-system/operation returns ~/.asdf/<name-of-system>.lisp. It's been said that an example is worth a 5.19 pictures so here are my preferences for asdf-binary-locations (in /users/gwking/.asdf/asdf-binary-locations.lisp):

(in-package asdf)
(setf *default-toplevel-directory*
      "/users/gwking/temporary/fasls/")
(setf *centralize-lisp-binaries* t)
;; force SBCL things to stay in SBCL
(setf *source-to-target-mappings*
      '(("/usr/local/lib/sbcl/" nil)
        ("/usr/local/lib/sbcl0.9.9" nil)
        ("/usr/local/lib/sbcl0.9.7" nil)))

These put all of my compiled files into sub-directories of ~/temporary/fasls (except for SBCL stuff which stay where they are expected).

The nice thing about this is that the preferences are loaded after the system whose preferences are being set is loaded. This is nice because it's hard to set preferences for a system that doesn't exist yet (because, for example, the home package of the variables you'd like to set isn't there).

(Thanks to the CCLAN and especially Christophe Rhodes who provided valuable feedback! Any remaining errors are probably the fault of either the Bush or the Clinton administrations. Or both of them together).


Those wacky biologists...
Tuesday, July 4, 2006

A team from the University of Ulm in Germany and the University of Zurich set a band of Saharan desert ants out questing for food. They eliminated direction as a factor by sending the ants through a long, straight tunnel. Once the ants reached the food, the scientists gathered them up and made some amendments to their legs: Some of the ants were fitted with stilts, while others had their appendages partially amputated.

Actually, I think that they had a great idea! Calling it "counting", however, reads more into the data than is available. Many animals are known to count accurately and to keep track of things like rate, etc. (Charles Gallistel's book is a wonderful read if you're interested in learning much, much, more!) but just because a human would solve a problem using solution X doesn't mean that an animal uses X too (even if we can't think of any other method to use than X...).


Updated: trivial shell
Monday, July 3, 2006

I fixed a typo in trivial-shell (sb!ext instead of sb-ext... go figure).


July Fourth in America
Monday, July 3, 2006

With apologies in advance for the politics... Howard Zinn says it for me:

On this July 4, we would do well to renounce nationalism and all its symbols: its flags, its pledges of allegiance, its anthems, its insistence in song that God must single out America to be blessed.

There's probably a bad joke here about Lisp being marginalized and America becoming increasingly marginalized -- or something -- but I don't want to think that hard.

... nationalism is given a special virulence when it is said to be blessed by Providence. Today we have a president, invading two countries in four years, who announced on the campaign trail last year that God speaks through him.

We need to refute the idea that our nation is different from, morally superior to, the other imperial powers of world history.

We need to assert our allegiance to the human race, and not to any one nation.

Transparency. Openness. Aim for the heights. Think the best of people. Do good and be nice.

keep peace.


Updated: CL-Graph
Saturday, July 1, 2006

Thanks to Attila Lendvai for some new patches to CL-Graph. He improved the GraphViz support and added some &allow-other-keys to avoid some warnings. I also just added the #'delete-all-edges generic function.


Two papers on Racer
Thursday, June 29, 2006

The semantic web is one of those great ideas that hasn't quite jelled. Eventually, the infrastructure, specifications and plans that are welling up out of the web's interstices are going to come together into something beautiful and strange. One of the droplets slouching towards us is Racer: a reasoner that takes all the little factoids expressed in RDF, DAML+OIL, OWL and so forth and derives consequences. These two papers (Racer: A Core Inference Engine for the Semantic Web and Racer: An OWL Reasoning Agent for the Semantic Web) share much of the same text so I'm describing them together. They provide a very high level overview of the various languages used to express semantic web knowledge (the acronym salad I listed above) and how Racer can use them to explore consistency, sub-classing (and other relationships), role filling and so forth. The papers describe several actual systems (e.g., RICE: Racer Interactive Client Environment, OilEd, and DIG). Neither paper is particularly useful in terms of giving compelling examples of how the semantic web is going to make our lives better (they give features not solutions) but they're a start.


#+Ignore is fine, #+(or) is bliss
Thursday, June 29, 2006

Although Common Lisp has a multiline-comment facility (that even handles nesting), many Lispers tend to use the #+ / #- reader macros to temporarily remove chunks of code from the view of the evaluator (note that these do not remove the code from the view of the reader, an issue which often leads to confusion the first time you can't load code that you think is 'commented' out — which is why it's important to remember that #+/#+ is not a commenting facility even though you may be using it like one...). The reason for this in my case is simple: laziness. I'd rather do something in one place than in two and it's easier to place (and remove) #+ignore in front of a form rather than wrapping the form in #| and |#. Frankly, I think that this sort of laziness is part of the human condition. If we really want most people to do the right thing most of the time, then we need to make it easy and convenient to do the right thing (e.g., recycle, carpool, keeping documentation up to date, and so on).

Using the reader macro to hide code isn't a bad practice as practices go (it's certainly healthier than coding in C or C++ <smile>) but lurking in the back of every coder's mind is that horrible question: "What if," they say to themselves in the still hours of the night, "What if someone pushes :ignore onto the *features* list?" (or :no, :later, :old, :new, :nil, :never, :not-yet, ...)? Well, I was looking at some of Peter Seibel's code recently and found a very nice way to have my cake even after eating it. There is form that is guaranteed to return nil regardless of what is on *features*? That form is #+(or) and it's a very nice thing indeed.


Microsoft is sharing code
Tuesday, June 27, 2006

I think that it will be interesting to see how this functions. Microsoft certainly has the resources to make it a useful code garden but I'm not sure if the political will is really there (shared source isn't open source). Coincidentally enough, one of the features I'd like to support at Enterprise Lisp is the ability to share Lisp code easily and with structure. The CLiki and Lisp Paste supply a good base but I think that a bit more infrastructure could make a bit difference in usability and utility.


Updates; E8EL is live
Tuesday, June 27, 2006

Thanks to the Tech Co-op, Enterprise Lisp is live and on-line in what I hope will be it's permanent home. System-check has been updated to version 0.1.6 to accommodate the new home.


Pretty wonderful (if you ask me...)
Saturday, June 24, 2006

Little brown dress:

I am making one small, personal attempt to confront consumerism by refusing to change my dress for 365 days.

I heard the artist interviewed last night on WAMC. I think it's great!


Ain't soccer grand
Saturday, June 24, 2006

Dynamic, fluid, a constant reinterpretation of tactics and strategy... like Life, like Lisp.


Sparklines + AJAX = nice
Thursday, June 22, 2006

Sparklines are little graphs that run in-line with your text. I believe that Edward Tufte invented them and I know that he talks about them in his upcoming book, Beautiful Evidence. Several folks have written code to create them (I think that there is even a Lisp implementation out there somewhere for CL-PDF?). Joe Gregorio has a nice Python AJAX web application if you want to play with them yourself.


How come Skype and Apple's Address Book don't play nice?
Thursday, June 22, 2006

Skype stores it's own contact data. How 1990s.


Common Lisp and RSS
Thursday, June 22, 2006

I've just started to start to work on an RSS feed for the Enterprise Lisp System Checker. The thing is, I can't find any Lisp libraries that make generating RSS feeds as easy as I think it should be (Kevin Rosenberg's CL-RSS is still available but seems unmaintained and only generates and parses RSS 0.92 feeds). So, in typical lisp hacker fashion, I wondered if I should first write a simple RSS library; something that can parse and generate RSS 0.92, RSS 1.0, RSS 2.0 and Atom feeds. If I did, there are two obvious designs: a object based one and a language based one. In the former, there would be classes for feeds and items and the usual things would happen to create, parse and generate feeds. In the later, RSS feeds would like like an XML template language (e.g., LML2, YACLML, and so forth).

The language approach would be conceptually simple but provides no useful abstractions (and no help in parsing). I think that templates make sense for a language like HTML because HTML content can be just about anything. RSS, on the other hand, always looks like a channel description and a list of items. The template just doesn't help that much. So on to objects and classes and such...


System Checker
Friday, June 16, 2006

The Enterprise Lisp system's checker has reached a stable point and I'm also happy with system-check. Unless I hear otherwise, the next steps will be (in no particular order):

  • Adding a Checker System status report - is it running, how many requests has it received, etc. Aside from helping me to know what things need focus, this information should be helpful to library writers and developers: what implementations are being used? How often are libraries changing, and so forth.
  • Adding an explain mode to system-check. Currently, update can tell you which of your libraries are out of date but I think that it might be helpful to see exactly which files have changed.
  • Creating an RSS feed to track which libraries are being updated. It might be nice to allow Lispers to register and customize the feed but I don't think I'll worry about that for a bit yet.

Once these features are stable (and once I've moved operations to a stable system), then I'll get back to ASDF-Install-tester / ASDF-Status and begin integrating them into Enterprise Lisp.


more various updates
Friday, June 16, 2006

ASDF-Binary-locations now knows about 64-bit OpenMCL (thanks to Joshua Moody for the heads up and the patch).

I've been having some troubles keeping the system currently hosting Enterprise Lisp up and running (those darn kids <smile>). I'm also ready to move over onto a virtual Xen thing run by the nice folks at GrokThis.

I've also improved the systems report slightly so that it is clearer what the systems checker found amiss. There are now five kinds of errors:

  • System not available - the tarball the CLiki points to is a 404
  • System file error - the tarball couldn't be digested for some other reason
  • Signature not available - the GPG signature file is a 404
  • Signature file error - the signature file made the checker unhappy for some other reason
  • Extraction Error - Something went amiss (obviously, this category needs to be broken out)

Note that signature problems can be restarted around (especially if you have the latest ASDF-Install) so it is possible to have a valid system and a valid signature even if the system status is not OK.


various updates
Thursday, June 15, 2006

  • CL-HTML-Parse - now happy for Allegro modern Lisp
  • CL-Graph - fixed bug in find-edge-between-vertexes that caused an infinite loop when both vertexes were not in the graph (Thanks to Joshua Moody)
  • CL-Containers - fixed bug in item-at-1 for alist-containers
  • ASDF-Binary-locations - now uses the file ~/.asdf/asdf-binary-locations.lisp to read preferences. This occurs after the code has been loaded and makes setting things like *source-to-target-mappings* a bit cleaner (IMHO). The pathname is created using:
(merge-pathnames
 (make-pathname :name "asdf-binary-locations"
                :type "lisp"
                :directory '(:relative ".asdf"))
 (truename (user-homedir-pathname)))

More why? (not Y)
Wednesday, June 14, 2006

I've received some follow-up on my "Why isn't Lisp da bomb for web development" post from last week. Since the CLiki isn't the place to talk about this kind of thing, I've made a little wiki at Infogami for it: lispandwebdev. Without going into details, the nub of the problem may be that Lispers are busy writing great stuff for the few whereas the Ruby on Rails folks et. al. are catering to the plebeian masses. I don't want to get sucked into language wars or anything like "my language is better than your language" or even the wistful "if only they could see it, then they would understand that Lisp is the way"... I also don't want to disparage the existing Lisp frameworks like BNKR, Lisp on Lines, UCW, the others I've forgotten and so forth. At issue, I think, is the sort of vitriol that leads to disasters like this (also noted by Stefan Scholl). This is happening very publically on Reddit and many people will have their prejudices created or confirmed that Lispers are arrogant smug weenies.

I find this almost unbearably sad.


ASDF-Install 0.5.5
Wednesday, June 14, 2006

Version 0.5.5 of ASDF-Install is ASDF-Installable and also available in the usual Darcs and tarball formats. This version starts to rationalize some of the where to look for system files registry management (i.e., there is now a function asdf-install:add-registry-location). It also adds a new restart so that packages can be installed even if there is no GPG signature file available (e.g., trivial-gray-streams).

See the change log for all the gory details)


two quick notes
Friday, June 9, 2006

I bumped up ASDF-Install to 0.5.4. The changes are very minor and serve only to make processing putative future keyword arguments a bit more consistent.

I also found a bug in system-check. At one point I had remembered to wrap my HTTP POST request in a with-standard-io-syntax but then I ran into some confusion with SBCL and I think pretty printing... To be honest, I never figured it out (slinks away with shame faced admission of guilt...). In any case, without the with-standard-io-syntax, it was quite possible for your personal print settings to muck things up badly (e.g., I have *print-length* set to 10 and the server didn't know what to do with an ellipsis). So, if you have already downloaded system-check, you might want to do so again. If you haven't, why, then, you should -- how is that supposed to be punctuated anyway? It makes sense in a conversation but I'm not sure how to write it... Anyway, please do check out system-check and let me know how to make it suit your needs.


Why?
Friday, June 9, 2006

Joel Reymont is leaning toward Ruby on Rails over Lisp for web application development and I don't get it. Joel is very smart and on top of things and I figure that he's right: Lisp just isn't there yet when it comes to building web applications quickly and easily unless you want to make it half your own private research project.

But Why? Lisp is good. Lisp excels at Domain Specific Languages. Lisp has the REPL for goodness sake. It can't just be that there are many Lisp dialects / implementations and that it's a bit hard to get, say, a socket library that works on all of them... can it? I mean, the MediaWiki runs on PHP (I think) and everything I've seen or heard about PHP is "...ick...". So why does the MediaWiki have all the loving goodness and we have the CLiki? (This isn't to diss the CLiki by the way, it's cool; I like it but as wikis go there isn't much there and nothing much has happened to it for ages.)

So bloggers on Planet Lisp, start your engines please... I'd like several essays from people who know the skinny on web dev and Lisp. Is Joel wrong? Is there a missing secret ingredient? what does Lisp need to come from behind in the web application development language race? After all, Ruby was a dark horse until Rails came along. The best essay gets a prize (to be announced later once I think of something).


That was fast
Friday, June 9, 2006

I bought a new hard drive for my laptop yesterday afternoon (the 8th) from PBParts.com. They promised that the drive would ship sometime before the 13th which seemed fine to me.

Guess what arrived today via FedEx. That's right, I've got the little thing already. It's always good to lower expectations but I'm very impressed.

It looks like a hardware kind of night tonight.


ASDF Checker report
Thursday, June 8, 2006

Here's the first ASDF Checker Summary report from Enterprise Lisp. The checker process runs daily and checks all of the known ASDF installable systems to see if they seem to work (i.e., that they download, have GPG signatures, that their system files seem to make sense and so on). The data from checker will be grist for tester once I finish refactoring ASDF-Install-tester to create it.

There is much room for improvement in the report (and feedback is welcome!). The last three columns show the system's status, whether we have a valid system file and whether or not we were able to create a system signature. The current system column isn't too useful; I need to spend a bit of time looking at the data and creating informative codes... A valid system is one whose system definition the checker could load -- it currently conveys no more information than whether or not the system has a status of error. Finally, the system signature is a list of the direct files of the systems and their universal times. Here are two examples:

? (dsc:system-signature 'moptilities)
(("moptilities.asd" . 3345750061) 
 ("dev:moptilities.lisp" . 3356703878))
? (dsc:system-signature 'anaphora)
(("anaphora.asd" . 3287421247)
 ("packages.lisp" . 3287421247)
 ("early.lisp" . 3287421247)
 ("symbolic.lisp" . 3287421247)
 ("anaphora.lisp" . 3287421247))
? 

These signatures are part of defsystem-compatibility. Checker needs to take more pains than it yet does to ensure that features and such don't influence signature computation. That's another one of the seemingly endless list of next steps!


On average I'm in the middle of a hot bed of Lisp activity
Wednesday, June 7, 2006

Unfortunately, the distribution is highly bimodal . My LinkedIn network shows that I have lots of connections in San Francisco and in England and Europe. Oh well, Lisp is catching on and eventually there is bound to more activity here. I wish that America had real high speed rail so that I could easily zoop down to NYC and get more involved with LispNYC.

If wishes were fishes... we'd all cast nets.


announce: system-check (beta)
Tuesday, June 6, 2006

Enterprise Lisp has been rumbling and grumbling slowly to life around me. Today I'm announcing the first beta of System-check, an asdf-upgrade like facility, that will eventually integrate with an improved ASDF-Install-tester and other cool things. The idea behind system-check is that it's easier to centralize the testing of Lisp libraries that it is to get all of the library developers to agree on versioning schemes and the like. Therefore Enterprise Lisp will regularly check on all ASDF installable systems and

  • make sure the system can be downloaded,
  • make sure that the GPG signature can be retrieved,
  • make sure that the signature file is valid,
  • make sure that the tar archive can be decompressed and
  • that the archive contains a valid system definition
  • that can be properly loaded into a lisp system

This will be coupled with an improved and distributed ASDF-Install-tester that can go on to make sure that systems actually do install on a variety of Lisps and environments.

System-Check is the client that you can run to see if your systems are up to date. Here is an example session (in OpenMCL). First, we load system-check. It displays instructions when it finishes loading:

? (asdf:oos 'asdf:load-op 'system-check)
; loading system definition from user-home:darcs;asdf-systems;system-check.asd.newest into #<Package "ASDF0">


----------------------------------------------------------------------
;; System-check helps keep your ASDF-Installable systems up to date 
;; by communicating with enterpriselisp.com via HTTP. Enterprise Lisp 
;; checks ASDF-Installable systems regularly to make sure that they 
;; work properly and install correctly.  
;; 
;; System-check has three main entry 
;; 
;; 1. update - checks all of your ASDF-Installed systems against the 
;; most recent available version and lets you select which ones to 
;; 
;; 2. gather - performs the same check as update but returns the 
;; results as a 
;; 
;; 3. check-system - performs a check on a single 
;; 
;; More information can be found in the documentation or at 
;; 
;; System-check can look for systems in several different 
;; 
;; * installed-systems (used by default) - returns a list of systems 
;; that seem to have been ASDF installed (see its documentation for 
;; 
;; * installable-systems - returns a list of all of the available 
;; systems (using 
;; 
;; Both of these functions take the keyword argument 
;; :only-asdf-installable?. If this is true, then System-check will 
;; query the CLiki to see if the system is ASDF installable.  
;; 

We cut to the chase and call the update function.

? (system-check:update)
Searching for systems.
; loading system definition from /Users/gwking/.asdf-install-dir/systems/cl-difflib.asd into #<Package "ASDF1">
; registering #<SYSTEM :CL-DIFFLIB #x84E1786> as CL-DIFFLIB
; loading system definition from /Users/gwking/.asdf-install-dir/systems/uffi.asd into #<Package "ASDF1">
; registering #<SYSTEM UFFI #x8514DE6> as UFFI

Checking 59 systems...........................................................

Results
============================================================
  4    we-are-latest  (local system has more recent changes than the remote)
------------------------------------------------------------
  xmls                          mk-defsystem                  
  cl-prevalence                 cl-html-diff                  


  6     both-changed  (system has modifications locally and remotely)
------------------------------------------------------------
  system-check                  metatilities                  
  lml2                          defsystem-compatibility       
  cl-graph                      cl-containers                 


  8            error  (the server was unable to check the system)
------------------------------------------------------------
  split-sequence                net-telent-date               
  ironclad                      clx                           
  cl-store                      asdf-install                  
  asdf-binary-locations         arnesi                        


 11      need-update  (remote system has changes)
------------------------------------------------------------
  trivial-http                  tinaa                         
  moptilities                   metacopy                      
  metabang-bind                 lift                          
  cl-variates                   cl-mathstats                  
  cl-html-parse                 asdf-system-connections       
  araneida                      


 30               ok  (local system is up to date)
------------------------------------------------------------
  xlunit                        wilbur-ext                    
  uffi                          trivial-configuration-parser  
  s-xml-rpc                     s-xml                         
  s-utils                       s-sysdeps                     
  s-http-server                 s-http-client                 
  s-base64                      rt                            
  puri                          md5                           
  lw-compat                     kmrcl                         
  html-encode                   diff                          
  contextl                      clsql                         
  closer-mop                    cl-utilities                  
  cl-fad                        cl-dot                        
  cl-difflib                    cl-base64                     
  cl-ajax                       cffi                          
  asdf-upgrade                  anaphora                      


Now that we've seen the report, we're asked what we want to update and ASDF-Install takes away the show.

We'll now ask which kinds of systems you want to update. 
You will be able to confirm before the update process 
begins.

11 systems need to be updated. Do you want to update them? (y or n)  y

Marking these systems for update: araneida, asdf-system-connections, cl-html-parse, cl-mathstats, cl-variates, lift, metabang-bind, metacopy, moptilities, tinaa, trivial-http.

6 systems are changed locally and remotely. Do you want to update them? (y or n)  n


Updating 11 systems
Install where?
0) System-wide install: 
   System in /Users/gwking/.asdf-install-dir/systems/site-systems/
   Files in /Users/gwking/.asdf-install-dir/systems/site/ 
1) Personal installation: 
   System in /Users/gwking/.asdf-install-dir/systems/
   Files in /Users/gwking/.asdf-install-dir/site/ 
2) Abort installation.
 --> 1
;;; ASDF-INSTALL: Downloading 531636 bytes from http://common-lisp.net/project/araneida/release/araneida-latest.tar.gz to araneida.asdf-install-tmp ...


"gpg: Signature made Fri Dec  2 12:55:13 2005 EST using DSA key ID 5E55AFEB" 
"[GNUPG:] ERRSIG 19876FCE5E55AFEB 17 2 00 1133546113 9" 
"[GNUPG:] NO_PUBKEY 19876FCE5E55AFEB" 
"gpg: Can't check signature: public key not found" 
> Error in process listener(1): No key found for key id 0x#1=(19876FCE5E55AFEB 17 2 00 1133546113 9). Try some command like 
>                                 gpg  --recv-keys 0x#1#
> While executing: #<Anonymous Function #x8426CE6>
> Type :POP to abort.
Type :? for other options.
1 > :r
0. Return to break level 1.
1. #<RESTART ABORT-BREAK #x2947FE>
2. Don't check GPG signature for this package
3. Retry GPG check (e.g., after downloading the key)
4. Return to toplevel.
5. #<RESTART ABORT-BREAK #x294CBE>
6. Reset this process
7. Kill this process
1 > (:c 2)
Invoking restart: Don't check GPG signature for this package
;;; ASDF-INSTALL: Installing araneida.asdf-install-tmp in /Users/gwking/.asdf-install-dir/site/, /Users/gwking/.asdf-install-dir/systems/
araneida-version-0.90.1/
;;; and so on...

We can also check the status of a single system. I'll turn on the verbose mode so that you can see what gets passed back and forth.

? (system-check:check-system 'anaphora :verbose? t)
Signature: (:SYSTEM :ANAPHORA :SIGNATURE (("anaphora.asd" . 3287421247)
 ("packages.lisp" . 3287421247) ("early.lisp" . 3287421247) ("symbolic.lisp" . 3287421247) 
("anaphora.lisp" . 3287421247)) 
:FEATURES (:KMR-MOP :CLX-ANSI-COMMON-LISP :ARANEIDA-THREADS :CL-FAD :CLOSER-MOP :ASDF-INSTALL :ASDF :GWKING :PRIMARY-CLASSES :CCL :CCL-2 
:CCL-3 :CCL-4 :CORAL :COMMON-LISP :MCL :OPENMCL :ANSI-CL :PROCESSES :UNIX :OPENMCL-NATIVE-THREADS :OPENMCL-PARTIAL-MOP 
:MCL-COMMON-MOP-SUBSET :OPENMCL-MOP-2 :POWERPC :PPC-TARGET :PPC-CLOS :PPC32-TARGET 
:PPC32-HOST :DARWINPPC-TARGET :DARWINPPC-HOST :DARWIN 
:POWEROPEN-TARGET :32-BIT-TARGET :32-BIT-HOST :BIG-ENDIAN-TARGET 
:BIG-ENDIAN-HOST :OPENMCL-PRIVATE-HASH-TABLES) 
:IMPLEMENTATION "openmcl-1.0-darwin-powerpc" 
:VERSION "0.1" 
:PATHNAME-SEPARATOR "/")
  Response: 200
  Headers: ((:DATE . "Wed, 07 Jun 2006 16:24:23 GMT") (:SERVER . "Apache/1.3.33 (Darwin) mod_lisp/2.43") 
(:SIGNATURE-RESULT . "NIL") (:POSTED-CONTENT . "(:SYSTEM :ANAPHORA :SIGNATURE ((\"anaphora.asd\" . 3287421247) (\"packages.lisp\" . 3287421247) (\"early.lisp\" . 3287421247) (\"symbolic.lisp\" . 3287421247) (\"anaphora.lisp\" . 3287421247)) :FEATURES (:KMR-MOP :CLX-ANSI-COMMON-LISP :ARANEIDA-THREADS :CL-FAD :CLOSER-MOP :ASDF-INSTALL :ASDF :GWKING :PRIMARY-CLASSES :CCL :CCL-2 :CCL-3 :CCL-4 :CORAL :COMMON-LISP :MCL :OPENMCL :ANSI-CL :PROCESSES :UNIX :OPENMCL-NATIVE-THREADS :OPENMCL-PARTIAL-MOP :MCL-COMMON-MOP-SUBSET :OPENMCL-MOP-2 :POWERPC :PPC-TARGET :PPC-CLOS :PPC32-TARGET :PPC32-HOST :DARWINPPC-TARGET :DARWINPPC-HOST :DARWIN :POWEROPEN-TARGET :32-BIT-TARGET :32-BIT-HOST :BIG-ENDIAN-TARGET :BIG-ENDIAN-HOST :OPENMCL-PRIVATE-HASH-TABLES) :IMPLEMENTATION \"openmcl-1.0-darwin-powerpc\" :VERSION \"0.1\" :PATHNAME-SEPARATOR \"/\")") 
(:CONTENT-LENGTH . "772") (:REMOTE-IP-ADDR . "155.212.227.170") (:REMOTE-IP-PORT . "30528") (:SCRIPT-FILENAME . "/Library/WebServer/Documents/compare.lsp") (:SERVER-IP-ADDR . "10.0.1.2") (:SERVER-IP-PORT . "80") (:SERVER-PROTOCOL . "HTTP/1.0") (:METHOD . "POST") 
(:URL . "http://metabang.gotdns.com/compare.lsp") (:SERVER-ID . "metabang") (:SERVER-BASEVERSION . "Apache/1.3.28") (:MODLISP-VERSION . "2.43") (:HOST . "metabang.gotdns.com") (:USER-AGENT . "simple HTTP for Common Lisp")
 (:CONNECTION . "close") (:CONTENT-TYPE . "x-www-form-urlencoded"))
:OK
?

System-check and the Enterprise Lisp system checker are both in beta at the moment. I've tested on several lisps but expect that problems and edge cases remain. Please let me know if you try system-check and it fails. I'm also working on some improvements to ASDF-Install so that it can behave more reasonably when installing multiple systems and with improving the back and forth between the client and the server. Enterprise Lisp is all about making Lisp easier for everyone, so please let me know if anything seems awry.


announce: simple-http
Tuesday, June 6, 2006

The world didn't need another HTTP library. Unfortunately, I did. Thus is born Simple-HTTP. It builds on the base of Trivial-HTTP and adds things like HTTP Head, HTTP download and HTTP-resolve. Eventually, it will be pulling in some useful bits and pieces from Lemonodor and Lisp Paste (e.g., here and here). Those that know should tell me what else would be worth adding. Enjoy.


announce: improved CL-Markdown
Monday, June 5, 2006

These changes aren't nearly as cool as ABL's but CL-Markdown has taken another few small steps forward toward Markdown compliance. The latest code tweaks the block structure processing and improves paragraph recognition logic. This means that its output looks more like that produced with the real markdown.


announce: improved asdf-binary-locations
Monday, June 5, 2006

Thanks to a patch from Peter Seibel and several good ideas and hints from Robert Goldman, ASDF-Binary-Locations has some changes and improvements. The most significant change is that the variable *system-configuration-paths* has been renamed to source-to-target-mappings* because the latter name is, IMHO, much, much better than the former. There are also two new variables to control behavior and the innards have been rewritten with generic functions so that you can have fine control over where exactly things go at both the system, the operation and the component level.

The three control variables are:

  • *centralize-lisp-binaries* - If true, compiled lisp files without an explicit mapping (see *source-to-target-mappings*) will be placed in subdirectories of *default-toplevel-directory*. If false, then compiled lisp files without an explicitly mapping will be placed in subdirectories of their sources.
  • *default-toplevel-directory* - If *centralize-lisp-binaries* is true, then compiled lisp files without an explicit mapping \(see *source-to-target-mappings*\) will be placed in subdirectories of *default-toplevel-directory*.
  • *source-to-target-mappings* - The *source-to-target-mappings* variable specifies mappings from source to target. If the target is nil, then it means to not map the source to anything. I.e., to leave it as is. This has the effect of turning off ASDF-Binary-Locations for the given source directory.

Note that if you've already set *system-configuration-paths* (e.g., in you lisp startup file), then ASDF-Binary-Locations will warn you about the change and automagically set *source-to-target-mappings* to whatever value you gave *system-configuration-paths*.

Also note that the finer control mentioned about has not been extensively tested (i.e., it really hasn't been tested at all) yet but will be once I finish the test suite. Won't that be sweet!

Please let me know if your milage varies.


more identity theft on the way...
Sunday, June 4, 2006

The names and credit-card numbers of 243,000 Hotels.com customers were on a laptop computer stolen from an employee of accounting firm Ernst & Young, according to sources familiar with the matter.

is it standard practice to provide auditors with names and credit care numbers? Why would they need that information? Why aren't they given anonymized data? If "The security and confidentiality of our client information is of critical importance to Ernst & Young", then why don't they do more to take it seriously?


the Golem's Eye
Wednesday, May 31, 2006

Book two of the Bartimaeus trilogy finds the magician Nicholas and the Djinn Bartimaeus once again embroiled in the scheming power politics of an Europe where magic rules. Hidden forces further devious plots: the resistance returns and is betrayed from within; a Golem is destroying the city; betrayal and duplicity abound. In short, it's a lot of fun and worth the enjoyable read. Yes, it is a book for young adults (hey, I'm only 42 (and that, as I suddenly recall, is the answer to everything)) but you'll probably enjoy it too.


the Amulet of Samarkand
Wednesday, May 31, 2006

One of the pleasures of having kids is that you can read kids book without feeling that you're too old to be reading them. The Amulet of Samarkand is very much a kids book but its a good one and it comes with interstitial themes worthy of adults. The book tells the tale of an earth where magic works thanks to the ability of some humans to summon spirits of all kinds. It is part one of the three part Bartimaeus trilogy (the eponymous name comes from that of the main narrator, a djinn of remarkable ability (including much sarcasm and wit). Amulet follows a complex plot with a young hero/anti-hero, many magicians of dubious intent, political scheming and many levels, a anti-magical resistance and enough twists to confuse an adder. It is all painted with a broad brush full of vim, verve and vitality. Buried under all this enjoyable fluff, however, are the messages that power is often neither to be trusted, nor desired; that the beneficence of a government is often inversely proportional to how loudly it congratulates itself; and that (to quote Bruce Cockburn) "when you get down to the bottom, loves the only thing that matters."


It's probably because I'm tired
Tuesday, May 30, 2006

and it's unlikely you really want to know. Nonetheless, here is my response to the iDon't marketing campaign of sandisk

Yes. We are all individuals. But good taste means buying high quality, extremely usable music players that work circles around the competition. This "oh so hip" concealed ad of yours is tacky, tasteless and offensive. iDo iListen to my iPod. iDon't listen, buy or even want to see a sandisk knock off. Get a grip. Get a life. If you want to sell music players, make a good one and stop insulting success.

ok, no more venting until at least tomorrow... (hmm, that gives me 7-minutes).


CLSQL and me: I feel so Microsoft Access ugly
Tuesday, May 30, 2006

I did a bunch of database stuff back when SQL 92 was exciting. I used early PC database systems like dBase IV, Foxpro, Borland's Paradox, and Microsoft's Access. Since auto-increment columns hadn't reached down to those trenches, I ended up doing the old "keep track of the maximum key in a separate key table yourself" trick. Not fun, but effective -- well, it works.

Today, I was messing with CLSQL (connecting to SQLite) and felt stymied trying to correctly get my primary keys to work. In the hopes that a wiser soul will feel my pain, here is what I did.

(def-view-class primary-key-mixin ()
  ((id :db-kind :base :type integer
       :db-constraints (:primary-key)
       :reader id :initarg :id)
   (table-name :db-kind :virtual 
	       :reader table-name
	       :initarg :table-name)))

(defmethod initialize-instance :after ((instance primary-key-mixin) &key)
  (unless (and (slot-boundp instance 'id) (id instance))
    (setf (slot-value instance 'id) (find-next-id (table-name instance)))))
					
(def-view-class sample-table (primary-key-mixin)
  ((name :db-kind :base :type (varchar 40)
	 :db-constraints (:unique :not-null)
	 :accessor name :initarg :name))
  (:default-initargs
      :table-name "managed-system"))

(def-view-class primary-key ()
  ((table-name :db-kind :base 
	       :db-constraints :primary-key
	       :type (string 20)
	       :accessor table-name
	       :initarg :table-name)
   (max-key :db-kind :base :type integer
	    :accessor max-key
	    :initarg :max-key
	    :initform 0)))

(defun recreate-tables (&key really?)
  (unless really?
    (cerror "Yes, really!" "Do you really want to trash the tables and start fresh?"))
  (clsql:drop-table [primary-key] :if-does-not-exist :ignore)
  (create-view-from-class 'primary-key)
  (clsql:drop-table [sample-table] :if-does-not-exist :ignore)
  (create-view-from-class 'sample-table)
  )

(defun find-next-id (table-name)
  (with-transaction nil
    (bind ((exists?
	    (select [max-key] 
		    :from [primary-key]
		    :where [= [table-name] table-name]
		    :flatp t))
           (next-key (if exists? (1+ (first exists?)) 0)))
      (if exists?
        (update-records [primary-key]
			:av-pairs `(([max-key] ,next-key))
			:where [= [table-name] table-name])
        (insert-records
         :into [primary-key]
         :av-pairs `(([table-name] ,table-name) ([max-key] ,next-key))))
      (values next-key))))

This defines two view-classes (and the recreate-tables function makes tables out them). The primary-key table keeps track of the highest key assigned so far; the primary-key-mixin uses it to assign keys as necessary. Since instances can be created and not added to the database, it's quite likely that we'll have gaps but that's not a big deal. This let's me execute code like:

? (setf *s* (make-instance 'sample-table :name "Gary"))
#<MANAGED-SYSTEM #x88C5F8E>
? (update-records-from-instance *s*)
; no value
? (setf *s* (make-instance 'sample-table :name "Wendy"))
#<MANAGED-SYSTEM #x88C5F9A>
? (update-records-from-instance *s*)
; no value
? (select [*] :from [managed-system])
(("cl-containers" 0) ("moptilities" 1))
("NAME" "ID")

Which, while not really exciting, is at least moderately painless. Aside from the fact that doing all of this key management myself strikes me as unbearably last decade (not to mention error prone and probably non-union), I figure that there must be a better way.

Any suggestions?


asdf:test-op redux
Tuesday, May 30, 2006

I wrote about asdf:test-op a bit ago and have since modified many of my opinions as to the way to do it. Yesterday, I noticed that Greg Pfeil had come to exactly my new conclusions back in late March (I read planet lisp quasi-religiously but missed this somehow). The chief changes are to move most everything to the system definition (not the test system definition) so that

(asdf:oos 'asdf:test-op 'my-system)

will test my-system (makes sense!). The only bit Greg leaves out is

(defmethod operation-done-p 
           ((o test-op)
            (c (eql (find-system 'moptilities))))
  (values nil))

Which keeps ASDF thinking that your test operation hasn't been done. (As we all know, testing is never done). Thanks Greg.


Comments?
Sunday, May 28, 2006

I've been meaning (and hoping) to write my own simple comment engine for the last upteen months. Today, I broke down and signed up with Haloscan. I'm not sure how customizable it can be or how I'll like it but I'm willing to see what happens.


Daring fireball
Sunday, May 28, 2006

I like John Gruber.

Can anyone explain how this seven-tiered edition plan is good for anyone other than the managers within Microsoft's bureaucracy? Microsoft is turning into a company that values management decisions that increase complexity over design decisions that increase clarity.

I love simplicity. I don't want to fight with my machine or with my inner mustard chooser. Too often, too much is not more than enough, it's too damn much.


Bellwether
Sunday, May 28, 2006

When I mentioned fads last week, Bill Clementson was kind enough to recommend me two books: bellwether by Connie Willis and Pattern Recognition by William Gibson. I've read quite a bit of Gibson's work over the years -- dark, but interesting -- but had never even heard of Willis. After reading bellwether, I'm very happy to have finally been introduced.

Willis is a delightful writer whose characters speak with the sort of ironic detachment of the modern person and yet still remain fully human and approachable (in this, she reminds me of Walker Percy). Her subject in bellwether, appropriately enough, is fads and trends and why it is that they ebb and flow across the human condition subject to a tidal pull all their own. The book offers an answer (though I don't think Willis believes it completely): that genius arises out of chaos, as a sort of self-organized criticality that forms because anything else would cause total system collapse; and that trends are both part of this self-organization and also the result of human bellwethers who are "a little faster, a little more greedy". Bellwethers lead without leading (though not in the Taoist sense <smile>) and move at least partly to their own deep beat... pulling at least some of the rest of us in their wake.

Regardless of its sociological value, however, this book is a wonderful read. Highly recommended.


Slurp
Saturday, May 27, 2006

Slurping up files is one of Perl's strengths and I've always assumed that Lisp could not do as well. I was wrong. This slurping in Lisp page demonstrates how at least some Lisps can do Perl one better. I found it via Stefan School's blog. Go Lisp, go!


brief note on CL-Graph
Friday, May 26, 2006

Someone rightly mentioned to me that CL-Graph doesn't have much in the way of a high level overview. Tinaa documentation isn't bad for seeing the trees but it doesn't make the forest any easier to navigate. Here, then is a very brief snapshot of CL-Graph from on high:

Structurally, a graph is a container-uses-nodes-mixin. This means that the things you put in the container are wrapped up in some other structure (a node). Examples of containers that use nodes are graph-container, binary-search-tree, heap-container. Examples of containers without nodes are list-container, array-container, basic-queue and so forth. In practice, this means that when you add a thing to a graph, the thing gets wrapped up in a vertex structure. When you do a find-vertex, you get back the vertex structure (not the element you added). For example:

? (add-vertex *graph* 23)
#<23>
:new        ; tells you that this was a new vertex
? (find-vertex *graph* 23)
#<23>     ; the vertex
? (describe *)
#<23>
Class: #<STANDARD-CLASS GRAPH-CONTAINER-VERTEX>
Wrapper: #<CCL::CLASS-WRAPPER GRAPH-CONTAINER-VERTEX #x8686356>
Instance slots
ELEMENT: 23
DEPTH-LEVEL: 0
VERTEX-ID: 0
TAG: NIL
GRAPH: #<GRAPH-CONTAINER [1,0] #x8E0EBD6>
COLOR: NIL
RANK: NIL
PREVIOUS-NODE: NIL
NEXT-NODE: NIL
DISCOVERY-TIME: -1
FINISH-TIME: -1
VERTEX-EDGES: #<VECTOR-CONTAINER 0 #x8E0B3EE>
; No value
? (element (find-vertex *graph* 23)) => 23
23

The main functions for creating and querying graphs are add-vertex / find-vertex / delete-vertex and add-edge-between-vertexes / find-edge-between-vertexes and delete-edge-between-vertexes. Once you have a graph or a vertex, you can map a function over its elements / edges using iterate-elements or iterate-edges. If you want to actually map over the vertexes, you can use iterate-nodes. There are also lots of iteration / collection functions for dealing with the children and parents of vertexes in directed graphs.

Quite a lot of CL-Graph is bound up with different ways of querying, collecting and iterating over the graph structures. It also has some simple graph algorithms (mostly of the summary sort like clustering coefficient, vertex degree, etc.) and it has decent export to DOT and integration with GraphViz. It's main claim to fame is that it does a good deal of bookkeeping to keep track of vertexes and edges so that you can concentrate on using the graph to do your stuff.


Notes on a Lisp Library Management
Thursday, May 25, 2006

I'm continuing to muddle through various ideas for Enterprise Lisp. One thing I think that the Lisp community needs is better library management. This means:

  • System definition
  • New System installation
  • System maintenance

ASDF (and MK-Defsystem and a few other defsystems) serve the system definition role admirably. My own defsystem-compatibiliy aims to make it easier to use multiple defsystems simultaneously (*). ASDF-Install does a great job grabbing new systems. The missing piece is system maintenance: making sure you have the latest of every and that it all works together. What follows is my proposal for improving the situation.

Desiderata

  • System maintainers want to do a good job but managing version numbers is difficult, time consuming and often goes undone.
  • System consumers just want things to work
  • If the process that handles system maintenance runs on the client, then you add another layer of things that must be maintained. Therefore, put as much computation on the server. (**)

The view from above

The system maintainer consists of the following processes:

  • Checker - monitor known systems for changes. When changes occur, generate tickets for Tester.
  • Tester - Test system installation (similar to ASDF-Install-Tester). Note that Tester is distributed across different machine architectures and Lisps.
  • Reporter - Use the results from Checker and Tester to produce pretty pictures, update RSS feeds, send text messages, generate press releases, call out the national guard, etc.
  • Clients (that's us!) - communicate with Webber to see if systems need to be updated
  • Webber - Communicate with clients (generally ASDF-Install) to determine if systems need to be updated.

Questions and Answers

This is the section where careful readers get to catch my errors and e-mail me as to how to make things better... So pay attention.

Q: What do you mean by known systems? A: Initially, Checker will work with ASDF-Installable systems. The main point of this, however, is to let Checker know where a system is to be found so there is no reason that other systems could not be registered for the service.

Q: How does checker know when a system has changed? A: Checker does two periodic checks on known systems. First, it compares the :last-modified date of an HTTP head request. If the last-modified date of the systems tarball is greater than the date Checker saw before, then the system may have changed. Secondly, Checker uses the system definition to build a system signature: a list of system files and file-write dates. Checker can compare the signature it has with the new signature to see if files have been added or removed and to see if file dates have changed. Note that occasional false positives are OK.

Q: What about *features*? Won't they mess with this signature you're talking about? A: Yes, features are a problem. For the curious, there are 52 systems on the Cliki that contain features in their system defs (out of about 250). These systems contain 40 different features. Most of them are operating system or Lisp implementation related. A few are more specialized. I propose to get around the features problem by using a custom reader to grab every file in a system definition.

Conclusion

The system described above is being actively developed and I hope to have something beta-testable sometime this work (oh, oh, that sounds like a promise. I have to stop writing now and get back to coding). Please let me hear from you if I've missed something obvious or subtle.


(*) To be fair, defsystem-compatibility (DSC) currently only supports ASDF and EKSL's system definer: Generic Load Utilities. However, only time and lack of clamor prevents DSC from working with others.

(**) Yes, this gives a central point of failure but web server and hardware is up to the task.


On the evolution of libraries
Wednesday, May 24, 2006

Lately, I've been pondering on the problems of library evolution. At one extreme of library creation is the put-it-all-in-here. At the other is the carve-nature-at-its-joints and have lots of dependencies. Philosophically, I tend towards the latter because shared code sucks (do it once, do it right) but it leaves one with an icky library management problem.

Then there's the issue of what to do with patches and additions? If a maintainer exists, patches and additions can pass through them. If there isn't a maintainer or if they find the changes don't fit with their vision of the library, then what happens? One can create a fork -- but that adds another library that may have issues working with the pre-fork version and it raises the code duplication issue in spades. One can also create another library that depends on the original... now we just have the yet-another-library problem.

It's interesting that we're culturally willing to create websites as wikis and are finding ways to deal with the problems of attribution and controversy. What would happen if we had a code wiki where everyone could edit everything. It's a scary thought because it takes so little to make code fail and because a little code can do a lot of damage very quickly (the software fault travels around the world before the patch gets out of bed or something...). Rambling on, this makes me think of the difference between syntax and semantics: word wikis work pretty well because they use language to pass around semantic knowledge and humans are remarkably good at dealing with faults. Code webs deal only in syntax and computers are almost unbearably brittle. The magic of computing, as my PhD advisor liked to say, is that it performs semantic transformations using only syntax. The problem is that the semantics all comes from the programmer. So what sort of infrastructures would make a code wiki possible?


Ora Lassila on the semantic web
Tuesday, May 23, 2006

Ora Lassila, a research fellow at Nokia, gave an interesting sounding talk (pdf) last week to the W3C advisory committee (I wasn't there, I'm just name dropping - smirk). His slides have include these provocative bullets:

  • Any specific problem (typically) has a specific solution that does not require Semantic Web technologies
  • Question: Why then is the Semantic Web so attractive? Answer: For future-proofing.

I think that this sounds about right and is part of the reason for the general attractiveness of XML and Lisp : code is data is code. When we need to, we can grovel over our source easily and do cool stuff.


Social Phenomenom (er, Phenomenon)
Tuesday, May 23, 2006

I've been looking at Ruby quite recently while working on Montezuma with John Wiseman on a port of Ferret (which is a ruby port of the java Lucene text indexing engine). I don't see anything particularly special about Ruby; overall, it seems like another reinvention of the wheel with more syntax with which to be confused! That said, all these "scripting plus" languages do fit a niche that Lisp has not been able to play in because Lisp has too much baggage (in my holy opinion) and because Lisp qua Lisp is missing the batteries like sockets, web services, etc...

What I find most interesting, however, is the social phenomenon: why and how did Ruby and Python make it to the big time? Why did Harry Potter become such a hit? Ruby, Python and Harry are all good but none of them seem, to me, markedly better than their competitors... Who researches this kind of stuff? Are there papers out there that claim to explain what is going on? Tipping Point? Wisdom of Crowds. Where is Malcom Gladwell when you need him?


the Problem with Threads
Tuesday, May 23, 2006

Someone mentioned Edward A. Lee's The Problems with Threads paper over at Lambda the Ultimate and I just finished reading it. The argument is simple: people live in a concurrent world so concurrent programming shouldn't be all that hard. But concurrent programming with threads is very hard so what's the problem? The problem is that threads are strongly non-deterministic and programmers (and languages and frameworks) must make great efforts to recreate determinism. It would be better, thinks Lee, to keep everything as deterministic as possible and only add non-determinism when necessary. I.e., we need better abstractions (perhaps built on top of threads).

Lee goes on to mention many of the alternatives and suggests that they have not taken deep roots in part because they are not necessary (yet -- there just aren't enough massively parallel non-trivial systems in use), because sequential programming is at the heart of all mainstream languages (and most non-mainstream ones too), and because it's hard to do multi-language programming (tool support, etc). The message, he says, is clear: "we should not [aim to] replace existing languages." He suggest coordination languages as a different extension mechanism (think Aspects and weavers) but even those have a hard time taking root because "language wars are religious wars and few of these religions are polytheistic" (I love that quote). He cites work with graphical notations and draws the parallel to UML's ability to abstract above specific language syntax and allow multi-languge use. There is, he hopes, hope.

This is a very readable paper with great examples and stories about had hard (thread based) parallelism can be and is. I don't know if his answers are correct (but who am I to know?! <smile>) but I strongly agree that we do need better models of computation and better languages to support those models. This should, perhaps, give Lispers hope. After all, what language to you know that is better positioned to support malleable syntax and coordination language experimentation?


Apologies: it was my fault, not CL-Markdown's
Tuesday, May 23, 2006

I meant &lt;pre&gt;. Depressing.


CL-Markdown update
Monday, May 22, 2006

I've removed CL-Markdown's dependency on LML2 (though CL-Markdown-Test still uses it to generate the comparison reports). I've also fixed several small tickets. The most important one probably being the correct handling of line breaks with <pre>s sections. I also changed the signature of the markdown form. The new one looks like:

Convert source into a markdown document object and optionally render it to stream using format. Source can be either a string or a pathname or a stream. Stream is like the stream argument in format; it can be a pathname or t (short for *standard-output*) or nil (which will place the output into a string). Format can be :html or :none. In the latter case, no output will be generated.

The markdown command returns (as multiple values) the generated document object and any return value from the rendering (e.g., the string produced when the stream is nil).

I hope that's clear. It makes it easy to go from strings or files to strings or files in any supported format (i.e., in HTML ).

There is still some distance to go before the basics are complete but things are starting to look pretty good.


Proving once again that I can do math, but not arithmatic...
Thursday, May 18, 2006

Michael Price wins the prize for quickly informing me that the version number of ASDF-Install on the website was 0.5.1, rather than the 0.5.2 that I had claimed. This should now be fixed. I should also mention that ASDF-Install has a new mailing list all to itself. See asdf-install-devel for details.

Finally, I'm in the process of bringing the tutorial back up to date.


ASDF-Install update
Thursday, May 18, 2006

The version now on Common-Lisp.net has been radically restructured and also has several patches and improvements. The restructuring just pulls various related forms out of installer.lisp and into their own homes. Mostly, this was to help me organize and maintain it. The improvements include:

  • More restarts involving the GPG key verification process so that, for example, you can switch to another process, retrieve a key and then try again.
  • ASDF-Install now prints its version string when it is first loaded (it's at 0.5.2).
  • I've tried to simplify the #+ / #- madness. There is still a ways to go for this to be complete.
  • Note that ASDF-Install now only installs the packages you request and their required dependencies. Earlier versions would install the package associated with every system definition that it downloaded.
  • There is a new keyword argument for the install command. If you specify :propagate t, then install will try to get the latest version of every package required during the installation. If propagate is nil (the default and previous behavior), then ASDF will only download the requested package and any that you do not yet have. It will not download any packages that you have already installed. Note that ASDF-Install still isn't doing any useful version checking, but being able to ask for everything fresh seems like a useful stopgap measure.

Please let me know if anything goes astray.


Software status update
Thursday, May 18, 2006

  • CL-Markdown : now works with SBCL, OpenMCL, and Allegro (alisp only at this point). Please post tickets to the Trac.
  • Trivial-Shell now exists (with thanks to Kevin Rosenberg and Alexander Repenning. Current interface is very trivial, some more stuff coming soonish.
  • ASDF-Install has moved to Common-Lisp.net. The version there has been restructured and has several improvements. It has a Trac too.

Doing it like we've always done
Sunday, May 14, 2006

A nice essay on the dangers of resting on our mental laurels

In the practice of security we have accumulated a number of "rules of thumb" that many people accept without careful consideration. Some of these get included in policies, and thus may get propagated to environments they were not meant to address. It is also the case that as technology changes, the underlying (and unstated) assumptions underlying these bits of conventional wisdom also change. The result is a stale policy that may no longer be effective…or possibly even dangerous.

...

This is DESPITE the fact that any reasonable analysis shows that a monthly password change has little or no end impact on improving security! It is a "best practice" based on experience 30 years ago with non-networked mainframes in a DoD environment — hardly a match for today's systems, especially in academia!


Enterprise Lisp Wiki
Saturday, May 13, 2006

I just created a simple wiki for Enterprise Lisp on Infogami (yes, they are the same people that did Reddit. So. <smile>). You'll need to join in order to edit. Let me know if that's a problem for you. I'm happy to post changes and ideas from other people if they send me an e-mail.


Drew McDermott and anti-literacy
Saturday, May 13, 2006

Drew McDermott has a nice essay on the benefits and difficulties of literate programming. The bit that resonates with me the most is this paragraph:

During program development, I tend to build a partial solution to a problem, then realize it's wrong and discard it or turn it inside out. It's very hard to force yourself to write a bunch of prose during this process; not only is the writing mostly wasted, it slows down your thought processes.

except that I find this happening to me about three-quarters of the time that I try test-first development. I don't know exactly what I'm doing (cf. Paul Graham's wonderful introduction to On Lisp or ANSI Standard Lisp (I can't remember which one)) and writing tests often turns out to be silly. Perhaps I'm just not getting out or can't rid myself of other bad habits or perhaps test first isn't something that makes sense all of the time.


On Selfish Memes: Culture as complex adaptive system
Saturday, May 13, 2006

This is a paper (pdf) that hits all the buzzwords hard and then hits them some more. We've got evolution, complex adaptive systems, power laws, dynamical systems, fitness landscapes, memes, phemes, and all the rest. The goal is to use memetics (which sounds way too muchlike dianetics to make me comfortable!) to explain culture and society. The chief problem is that (in the papers own words)

culture is multi-layer in hierarchies of description object, parts constituting the higher level of description non-linearly and so on. The important note we have from works on conventional cultural analysis is that culture is developed in the ways of how cultural units influence each other.

...

As a tool of cultural analysis, we can see by now that meme is a representation of diffused cultural unit. It is shown that meme concerns diffusion of the perceived; that is why memetics are close to the discussion about epidemiology of rumors (Lynch, 1998). If a meme pass through someone's brain by the process of perception, there is a process of interpretation and adoption before it goes to the next diffusion. However, the interpretation and adoption is frequent giving different output to be diffused. This is what we can see from our analysis and the above computational experiment and become the micro-properties of memetic process.

(The writing style -- loosely speaking -- doesn't help)

The level of abstraction hides some much philosophical sleight of hand and wooly thinking that no amount of formalism, charts and graphs can save us.

... meme is the cultural unit that imitated as an abstraction and neurally-stored in the brain. Since it is an abstraction, we are not allowed to assume meme as smallest information unit in cultural evolution in general, but it is the smallest information we use on explaining any cultural evolution. Thus, meme can be a very small part of cultural objects (e.g.: note of music, the way use of shoe) and even the big part of culture (e.g.: nationalism, religion). In other words, meme is a matter of analytical tool on explaining culture and its dissemination, propagation, and in general, evolutionary process.

This is one of the oldest self-inflicted tricks in the book of bad simulation: insert that which is to be proved into the foundations of the simulation and be astonished when the simulation acts that way (note that I'm not suggesting bad faith on the practitioner of the paper -- it's just that natural stupidity is something that must be fought against constantly.

In closing, I should mention that this paper is one of the references for a United States Army SBIR Request for Proposal. The RFP is reasonable enough but if this paper is supposed to be guidence... I'm more frightened than ever.