Blackthorn 3D — Lisp game engine using USerial June 20th, 2011
Patrick Stein

Elliott Slaughter announced Blackthorn 3D, yesterday. Blackthorn 3D is a game engine crafted in Lisp using LispbuilderSDL and cl-opengl for graphics and usocket and userial for network play.

C- in MacOSX’s Terminal.app June 14th, 2011
Patrick Stein

After tonight’s TC Lispers Meeting, I had a renewed interest in figuring out why C-<right arrow> didn’t work for me in Org-Mode or Paredit.

After a whole bunch of running in circles, I have discovered a combination that works (with these clues). I have my TERM variable set to xterm-color. I configured the Terminal.app using its Keyboard settings to have it send the string “\033[1;5C” for C-<right arrow> and “\033[1;5D” for C-<left arrow>. (The “\033” is the escape key.)

This works for me even through screen.

Bonus.

Quicklisp Win: Weblocks June 2nd, 2011
Patrick Stein

I was recently reminded of a presentation that I gave last year about Weblocks.

Here’s one slide from that presentation:

Today, I started from scratch in an empty account on an eight-year-old Linux box. I installed Quicklisp and used it to install Weblocks. I had a Weblocks server up and running in under three minutes.

Method Versions — v0.1.2011.05.18 May 18th, 2011
Patrick Stein

Edit: After re-reading some of the ContextL papers, I believe that I am actually just going to use ContextL as it’s a much more flexible superset of this library. I will probably still keep this library published as an example of a non-trivial, but glarkable, method combination.

I am releasing a new library that allows one to dispatch generic methods based on the value of a global parameter.

There are situations where one might like to dispatch a method on some information other than the required parameters of the method. For many situations, it is sufficient to switch between those methods based on some external parameter. The method-versions library allows one to do just that.

Obtaining

Internationalization Example

In this example, we do a silly form of internationalization. To that end, we will use English as the default language and define some other languages.

 (method-versions:define-method-version latin)
 (method-versions:define-method-version pig-latin)
 (method-versions:define-method-version french latin)
 (method-versions:define-method-version spanish latin)

We will prepare a language parameter and a welcome method that is versioned on the language.

 (declaim (special *language*))
 (defparameter *language* nil)
 
 (defgeneric welcome ()
   (:method-combination method-versions:method-version-method-combination
                        *language*))

And, we define welcome methods for the various languages (accidentally forgetting spanish).

 (defmethod welcome () :welcome)
 (defmethod welcome :latin     () :velkominum)
 (defmethod welcome :pig-latin () :elcomeway)
 (defmethod welcome :french    () :bonjour)

Then, we will try each of the languages in turn.

 (mapcar #'(lambda (ll)
             (let ((*language* ll))
               (welcome)))
         '(nil :latin :pig-latin :french :spanish))
 => (:welcome :velkominum :elcomeway :bonjour :velkominum)

Delayed Evaluation Across Packages April 24th, 2011
Patrick Stein

For my networking layer library, I wanted to provide ubiquitous logging. At the same time, I did not want to tie the application to my choice of logging library. I wanted the user to be able to pass me a function where I could give them a logging category and something to log.

(in-package :unet)

(defvar *logger-function* nil)

(defmacro log-it (category thing-to-log)
  `(when *logger-function*
     (funcall *logger-function* ,category ,thing-to-log)))

This seems simple enough, right? Now, throughout my code, I can do things like:

(log-it :incoming-packet packet)
(log-it :list-of-unacked-packets (get-list-of-unacked-packets))
(etc)

The application can register a *logger-function* something like this:

(defun app-log-network-msgs (category thing-to-log)
  (cl-log:log-message category thing-to-log))

Here’s the problem though: most (all?) logging libraries are good about not evaluating any arguments beyond the category unless something is actually listening for messages of that category. This makes it reasonable to do stuff like this and only take the speed hit when it’s actually important to do so:

(log-it :excruciating-detail
        (mapcar #'get-excrutiating-detail (append everyone everything)))

With my macro above, I have no way of knowing whether something is listening on a particular category or not. Further, most logging libraries don’t offer a way to query that sort of information.

What to do?

What I wanted to do was to pass a macro from the application package into my networking library instead of passing a function. I spent way too long trying to find a way to make this work (especially considering I ran into the same trouble in October, 2009 trying to use some combination of (macroexpand ...) and (eval ...) to let the caller decide which forms to execute).

All it took was posting to comp.lang.lisp to answer my own question: Closures. I changed my macro to create a closure:

(defmacro log-it (category thing-to-log)
  `(when *logger-function*
     (funcall *logger-function* ,category #'(lambda () ,thing-to-log))))

Now, the application’s logger function changes slightly and my forms are only evaluated when the logging library evaluates them:

(defun app-log-network-msgs (category thing-to-log-generator)
  (cl-log:log-message category (funcall thing-to-log-generator))

Hopefully, I will remember next time I run into this.

Updates In Email

Email:

l