20110130

All things being equal...

Alright, this has been floating around for some time and it is time to write it up.

Several object-oriented languages (e.g., Java, Ruby, C++, etc.) have ways to define equality and comparison operators or methods. In Java the Object class defines the equals method, which can be specialized in user code and the Comparable<T> interface.

In Common Lisp, while all the machinery is there to provide such facilities, there has been no push to provide them. I think there are two reasons for this. The first one lies in the widespread use of :test keywords and the programming style it encourages, especially when writing libraries. The second in the influential KMP's paper on The Best of Intentions: EQUAL Rights - and Wrongs - in Lisp.

The first reason does not really needs discussing, the second, a bit. In my honest opinion, there are no real reasons not to have a notion of generic equality (and comparisons) on top of the standard :test machinery, provided that some caution is taken.

Having said so, I built methods for the following generic functions.

(defgeneric AEQUALIS (a b &rest keys &key recursive-p &allow-other-keys)
 (:method ((a T) (b T) &rest keys &key recursive-p &allow-other-keys)
    (eq a b))
 )

(defgeneric COMPARE (a b &rest keys &key recursive-p &allow-other-keys)
   ...)

AEQUALIS is Latin for "equal". The generic function COMPARE returns <, >, =, or /=.

I prepared a specification for them (and an implementation) in order to post a CDR. You can find it in the CLEQCMP directory on my Google docs.

Comments welcome.

Enjoy


(cheers)

20110107

NEW project on common-lisp.net

There is a NEW project on common-lisp.net. The new-op pages contain documentation and download instructions to get the code for the new operator in Common Lisp I described in a previous post.
(cheers)

20101219

CLAZY and ENUMERATIONS

I submitted CLAZY and CL-ENUMERATIONS to Quicklisp and found out that there were some problems with them. Mostly due to (unwarranted) package locks in SBCL and CLISP. Fixing these problems led to some revisitation of the code base and subsequent improvements (I hope).

Both libraries should appear in future Quicklisp releases.


(cheers)

20101206

HTML in Common Lisp: code or fill?

I finally got around to write my very own HTML documentation system. Of course, this may be pointless and useless, but I found the alternatives "out there" lacking this or that (obviously!). So here I am, trying to automate the process of producing documentation like that of CLAZY, which I hand-crafted in the past. In the process, needless to say, I got carried away and got lost in the land of featurism only to contemplate my overall ignorance of most things webbish.

As usual, Edi Weitz came to my rescue by offering his CL-WHO and HTML-TEMPLATE, which raised a question: which of the two approaches is best? Note that the answer should consider how many dependencies my system files can have.

Let's start with the simple problem I have: I need to produce a .html file that contains, say, a "header" for my documentation. I could do it using CL-WHO in the following way (just a snippet, not working...)

(defun produce-header-file (fs header-pathname)
(declare (type frameset fs)
      (type pathname header-pathname))
(let ((fs-order (frameset-order fs))
   (fs-head-title (frameset-head-title fs))
   (fs-body-title (frameset-body-title fs))
   )
(with-open-file (hs header-pathname
                   :direction :output
                   :if-exists :supersede
                   :if-does-not-exist :create)
 (with-html-output (hs hs :indent t)
   (fmt "~A" (cl-fad:pathname-as-file header-pathname))
   (fmt +doctype-frameset-control-string+)
   (:html
    (:head
     (:title (str fs-head-title))
     (:link :rel "stylesheet" :href "clstyle.css"))
    (:body :style "margin: 0pt 0pt 0pt 0pt;"
     (:div
      :class "header"
      :style "padding-left: 2em; padding-top: 5pt; color: #41286f; font-size: 14pt"
      (:strong (str fs-body-title))
      (:div
       :class "navigation"
       :style "right: 2m"
       (:a
        :href "index.html"
        :class "navigation-link-selected"
        :target "_parent"
        (str "Home"))
       )))))
 )))

Or I could use HTML-TEMPLATE and ship around a "template" file like the following (again, this is just a snippet and contains errors):

<!-- header.html -->

<!DOCTYPE HTML PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html>
<head>
<title><!-- TMPL_VAR HEAD_TITLE --></title>
<link rel="stylesheet" href="clstyle.css">
</head>

<body style="margin: 0pt 0pt 0pt 0pt;">

<div class="header"
style="padding-left: 2em; padding-top: 5pt;  ">
<strong><i><!-- TMPL_VAR BODY_TITLE --></i></strong><br/>

<div class="navigation" style="right: 2m">
<!-- TMPL_LOOP frames -->
<!-- TMPL_IF current_frame -->
<a href=<!-- TMPL_VAR frame --> class="navigation-link-selected" target=_parent><!-- TMPL_VAR f_nav_name ->></a>
<!-- TMPL_ELSE -->
<a href=<!-- TMPL_VAR frame --> class="navigation-link" target=_parent><!-- TMPL_VAR f_nav_name ->></a>
<!-- /TMPL_IF -->
<!-- /TMPL_LOOP -->
</div>

</div>

</body>
</html>

<!-- end of file : header.html -->

I am inclined to go the CL-WHO way. I do not have to ship around an extra file and record its location etc etc; yet the HTML-TEMPLATE does have appeal. Any ideas out there?


(cheers)

20101005

NEW post

Hello,

here is a NEW post after a long time. And the topic of this post is NEW. Of course, this is old stuff, but here it is: it's a post about the new operator. I'd bet there are many other little hacks like this floating around, but I finally got sucked in into writing a little library that introduces a new operator (and a newq one) in Common Lisp.

Why? After a very long time of putting up with make-instance and make-this and make-that, and after many other brain things going on in my head (cit. King Julien of the Lemurs) I decided that Common Lisp needed something capable of doing the following:

cl-prompt> (defclass foo () ())
FOO
cl-prompt> (new 'foo)
#<FOO instance 42>

or even

cl-prompt> (newq foo)
#<FOO instance 42>

So; what's the big deal? Not much, but I also want to be able to write:

cl-prompt> (newq (array single-float (2 2)) '((1.0 0.0) (0.0 1.0)))
#2A((1.0 0.0) (0.0 1.0))

The problem is that as soon as you wade in CL "type specifiers" land, you hit the dreaded "implementation dependent" wall, or, worse, the "this is not even mentioned in the ANSI spec" wall. Think of DEFSTRUCT and the fact that there is no portable way to get to the constructor, not to mention DEFTYPE.

Apart from that, I think that the little piece of code I wrote would maybe make programming in CL feel more in tune with the times. After all you can also write things like the following, which I think are rather cool.

cl-prompt> (new '(mod 42) (read))
1024
Error: 1024 is not of type (INTEGER 0 (42)).
...

What do you think? Is this worth a CDR? Ping me if you want to see the code.


(cheers)

20090526

ELS 2009 tomorrow

Here it is. Tomorrow there will be the reception for the opening of the 2nd European Lisp Symposium 2009 in Milan (www.european-lisp-symposium.org) I look forward to see many of you here in Milan.
(cheers)

20090415

CL-UNIFICATION does regexps (thanks to Edi Weitz)

I have been working for some time on the CL-UNIFICATION library. Somehow, "unification" and "parsing" are related but not quite (I bet the literature on the topic is huge). In an afternoon of the Easter vacation, I decided to take the easy way out of extending CL-UNIFICATION with some "parsing" functionality: I just added Edi Weitz's wonderful CL-PPCRE library. Edis' library has a very simple and intuitive interface which made the integration a SMOP! The result is the following. Now you can write the following (assuming all the packages are USEed):

(unify #T(regexp "a(b+)c(d+)" (?bs ?ds)) "abbbbcddd")
The call will produce an environment where ?BS is bound to "bbbb" and ?DS is bound to "ddd". Here is a full transcript.
CL-USER 3 > (in-package "UNIFY")
#<The CL.EXT.DACF.UNIFICATION package, 326/512 internal, 20/64 external>

UNIFY 4 > (unify #T(regexp "a(b+)c(d+)" (?bs ?ds)) "abbbbcddd")
#<UNIFY ENVIRONMENT: 1 frame 200BC147>

UNIFY 5 > (v? '?bs *)
"bbbb"
T

UNIFY 6 > (v? '?ds **)
"ddd"
T
Of course, the other matching operations work as expected.
UNIFY 9 > (match-case ("abbbbcdd")
                      (#T(regexp "a(b+)c(d+)" (?bs ?ds)) (concatenate 'string ?ds ?bs))
                      (t "It did not work!"))
"ddbbbb"
I.e., there is an interface to get to the actual regexp groups (beyond those available directly in CL-PPCRE). Maybe the syntax of the regexp unification templates could be made even more CL-PPCRE-like by exploiting "named registers", but, for the time being, the above is the best way to use it.
(cheers)