Recently in Lisp Category

In Processing Hack Week news...this past week, I've received two replies to my requests for task lists from the various Processing derivative projects. One from the Ruby-Processing developer and the other from the Clojure-Processing developer. The other news is that the GIT-repo for Processing is coming together.

The other day I was going through some notes that I organize using Org-mode and I realized that it's a pain in the ass to write up links to Wikipedia entries all the time. So I whipped up some code that adds an org-mode link.

It's 1am and I have myself organized in terms of the meetups. I have a list of meetups and people who have shown up and can be considered regulars, I also have a template setup for discussing previous meetups. Also, this is the big thing, I have this in a GIT repo! So I can make whatever changes I want to the page offline and then simply copy/paste into the Association of Lisp Users wiki page for the Toronto Lisp Meetup.

The project is still alive. The last time I checked it looked a little dead, but now that I've checked out the mailing list archives, it looks like it's still alive. Awesome awesome :D

cl-terrace

Thanks to the list, I've discovered another web application framework for Common Lisp called cl-terrace. It's a Model-View-Controller framework (aren't they all?) with only the View-Controller part covered. I'm not sure exactly how that works, but it uses the Hunchentoot web server, and djula, a Common Lisp template engine based on the Django templating language which is nice.

The documentation for djula should be generated by the developer since the API is apparently changing around quite a bit. Djula looks like it handles internationalization and translations in a sane way. You specify translations using a dictionary (a.k.a. hash-table), the example shows how to do this.

cl-terrace is ASDF-installable in case you're itching to try it out. Using SBCL, run this:

(require 'asdf)
(require 'asdf-install)
(asdf-install:install 'cl-terrace)
to install it.

Ruby

On another note, a Ruby note, Chris Wanstrath of GitHub fame presented a keynote at the 2008 Ruby Hoedown about side projects where he said,

First off, the time issue. I don't know how many of you read RSS, but I challenge you (that's a keynote term) to give it up for a month. Just turn it off...What should you do instead? ...let other people do the filtering for you. Use your time for other things.

It's a good keynote and lots of communities could learn a thing or two from the Ruby community. The optimism of the community has to be balanced out as Unspace's Pete Forde says,

Folks in Ruby tend to write a lot of nostalgic, self-aggrandizing bullshit, though. You see a lot of "MY MY, THE COMMUNITY HAS EVOLVED INTO SOMETHING SPECIAL" and talk of changing the history of software development. I'm all for progress, and as a musician, I understand the function of hype in generating momentum. But sometimes we need to get real and be a little more harsh in our own self-analysis.

Anyway, off to write some code.

Mid-August Lisp News

Meetups

Toronto

7 August 2008, A very small gathering of Lisp users at the LinuxCaffe. Abram showed the inner workings of the game Abuse which uses Lisp for almost everything, except the core (which is written in C, this is similar to how Emacs works). An interesting question asked was whether or not the Abuse Lisp dialect supported macros, it seemed that the custom "macros" were all coded in C and thus untouchable. Next, a crazy mod that turns the game into a game of Super Mario was shown.

The disadvantages and misuse of car, cdr, caaaaar, cadaddarr, etc. were also mentioned. The consensus is that once you're using cadr, caddr, what you really want to be doing is creating a structure or object. That way you can access things by a descriptive name. An example of why this is a good idea is given by xmls, an XML parser. It parses XML and turns it into a giant list, with the first element being the element tag name, the second element being a list of element attributes, and the rest of this list being child elements. This can be tedious to navigate through.

Libraries for Scheme were also mentioned. The drawbacks of the various dialects of Scheme are that the specification does not define even the basics of common ways of dealing with libraries. Because of this, when you switch Schemes, you have to re-discover libraries that do what you want. This is an old complaint of course.

Lisp images and program startup costs were discussed in relation to Perl, PHP and Smalltalk. Some Lisps have the ability to dump a memory image and reload that later on. This improves the startup time since libraries are already loaded and not re-loaded or re-compiled. I noted that there doesn't seem to be a culture of image-sharing in the Lisp community as there is in the Smalltalk community. One reason suggested for this is that some Lisps run on 64-bit architectures and others run on 32-bit, which means code needs to re-compiled anyway. Perl and PHP were said to have no way of image dumping and this is particularly problematic for PHP since it seems to rebuild things for each website request. (This may be incorrect or a non-problem)

Finally, I mentioned traits in Smalltalk. Traits are collections of methods that can be used by classes and overridden (or not). Eiffel seems to have something similar, as does Ruby with mixins. Here is the paper that explains the idea more fully[PDF].

comp.lang.lisp

Kenny Tilton, the man behind Cells and Theory Y Algebra, asked why the special variable *default-pathname-defaults* is named that way. Pascal Costanza comes up with an answer and asks his own question in return,

Do you guys also worry about important problems?

Blogs

Xach's Cool Charts

Xach made some cool charts inspired by Tufte and stream graphs. The first chart shows movie box office data, while the second shows the version control activity of CMUCL and SBCL.

The charts were made using Vecto, a simple vector drawing library for Common Lisp.

cl-cairo2 updates

This is a nice update for cl-cairo2 users. Now cl-cairo2 loads only OS-independent parts of the library, with the OS-dependent parts becoming parts of extension packages.

Lisp Quiz

Lisp Quiz is inspired by Ruby Quiz which was inspired by Perl Quiz of the week. Ruby Quiz and Perl Quiz were weekly programming challenges, and Lisp Quiz hopes to do the same for the Lisp community. The first quiz tackles Minesweeper, having you design an algorithm that wins the game.

Everything Else

LispForum

LispForum, launched on 27 June 2008, is another place for Lisp-related discussion. It is run by Dave Roberts, the blogger who is behind the Finding Lisp blog. They have added a new sub-forum for Lisp Quiz puzzles which are supposed to be similar to the Ruby Quiz puzzles.

What's interesting about LispForum is that it's new (almost 2 months old, only!) and it already has 296 members. There are already 443 posts about Common Lisp, though there don't appear to be many Scheme fans. So we have yet another forum to recommend to newbie Lisp programmers.

Here's a function for Emacs that counts the number of words in a buffer by using a regular expression:

(defun wc ()
  (interactive)
  (message "Word count: %s" (how-many "\\w+" (point-min) (point-max))))

The regular expression matches against one or more word characters. It doesn't move the current point of the buffer so you don't have to keep re-positioning the cursor every time you run this function.

The reason I'm posting this is because I was searching for something like this and everyone keeps suggesting to use the "wc" shell command while in Linux, but I'm in Windows! How can I use it? Another thing I found is that people write up functions that loop through words and count them. I'm guilty of doing that, but using the above function is much much easier.

Emacs has most everything that you can think of. The problem is that it's all hidden away somewhere and you have to take the time to dig around.

Update: The how-many function is defined in replace.el. To find out more about it, press C-h f how-many RET.

I have gained an interest in cyberpunk novels again and have been looking at the Shadowrun RPG. One of the hallmarks of cyberpunk is a dark, depressing atmosphere. This darkness is also associated with the coolness that is running the shadows or jacking into the Matrix or whatever. But, I believe, there is a benefit to a dark-themed desktop: it hurts the eyes less after hours of staring at a light-themed desktop.

Oren Eini has written a DSL that uses the Boo language and does a bit of sub-classing. This was in response to a reply to one of his posts by a blogger named Tim Wilde. The purpose of a domain-specific language is to make it easier to talk about the domain. The DSL written is written for the domain of scheduling tasks. Instead of typing out the following:

myTask = new Task("warn if website not alive", (3 * 60), ... )
myTask.start()
You would type out:
task "warn if website not alive" every 3 minutes starting now ...

It's more readable for other users and it hides details that are unnecessary when talking about the domain.

Tim came up with a C# variant which had roughly 250 lines of code, 8 classes and 6 interfaces. Over-kill in my opinion. Oren came up with something that makes the DSL look cleaner and it uses the Boo language.

Oren says,

There are several interesting things that are going on in the DSL. For a start, we are using Boo's ability to drop parenthesizes if needed, which gives us a more "keyword" feeling. Another interesting approach is that when the last parameter of a method is a delegate, we can use just create a block and use that as a way to create the delegate.

The keyword feeling is fantastic. But it can be taken much further. Much much further. Lisp comes with very powerful macros that can be used to write DSLs and DSLs have been written in Lisp since before I was born in 1987. Being able to create a DSL by extending a language is nothing new. This is why I've implemented my own version of the above DSL in Lisp

My Implementation

Warning: I'm using the Scheme dialect and the MzScheme implementation. I'm using the MzScheme thread library instead of the official multi-threading extension to Scheme.

My implementation uses Scheme and the syntax-rules pattern language. I didn't much like it but now I am getting used it and may use it more often than the Common Lisp defmacro method. I have no idea exactly what the differences are since I am Lisp beginner, but I was able to use Scheme to write an implementation of this DSL in less than 30 minutes.

The code consists of 3 functions: 2 are placeholders, the other one converts whatever time is given into the equivalent amount in seconds. So, 1 minute turns into 60 seconds and 3 minutes turns into 180 seconds. This is used with the sleep function in each task's thread which controls how long to wait until the task is executed again.

The 2 Patterns Detected

The code also includes 1 syntax definition that has 2 similar patterns that it can match. The 1st pattern is triggered when the task is not starting immediately. An example:

(task "warn if website is not alive"
      every 3 seconds
      starting in 5 seconds
      when (not (website-alive? "http://example.org"))
      then (notify "admin@example.org" "server down!"))

The 2nd pattern is triggered when the task is starting immediately. This is triggered when the keyword "starting" is followed by the word "now". The above example re-written to start immediately.

(task "warn if website is not alive"
      every 3 seconds
      starting now
      when (not (website-alive? "http://example.org"))
      then (notify "admin@example.org" "server down!"))

Here is the final implementation:

(define-syntax task
  (syntax-rules (every starting when now then in)
    ((task task-name every time-value time-unit starting in start-value start-unit
	   when test then do-stuff ...)
     ;; The first thread waits
     (thread (lambda ()
	       (sleep (time->seconds start-value start-unit))
	       (thread
		(lambda () (let loop ()
			     (if test
				 (begin do-stuff ...))
			     (sleep (time->seconds time-value time-unit))
			     (loop)))))))
    ((task task-name every time-value time-unit starting now
	   when test then do-stuff ...)
     (thread (lambda () (let loop ()
			  (if test
			      (begin do-stuff ...))
			  (sleep (time->seconds time-value time-unit))
			  (loop)))))))

2 Interesting Things

2 interesting things that you must know about this code: literals and named let. Literals are using in the syntax-rules pattern language and are the 1st argument to the syntax-rules call. Literals allow us to include keywords in the pattern, such as now and when.

The other interesting thing is the used of the named let. This is when the 1st argument of a let call, a literal, is the name of the "function" created. The 2nd argument is the list of parameters which can include default values that the "function" will be called with. A named let is typically used to add a recursive loop in the middle of another function.

Conclusion

The download is available here. The code is very short...59 lines including comments. It uses no classes and no interfaces. Some ideas for improvements include hooking into a task/thread list so that tasks/threads can be killed or retrieved later on.

I've blogged about this only to show that Lisp can be used as well and can be more concise than other languages. DSLs are not a new idea but that doesn't mean I'm not happy that people are finding great uses for them.

Questions, corrections and comments are welcome!

A reddit user by the name of alanshutko stated what was necessary to make Scheme, Common Lisp, Haskell, and other non-mainstream languages more appealing to the average programmer.

Compare that with the types of simple programs we see in Perl and Python. "I have a bunch of files, and I want to rename them all according to some pattern." Common problem, easy solution. "I've got a log file full of email addresses, I need to strip them out from the log entries, remove duplicates, and add them to a database." Again, fairly simple, fairly small, really useful. When Haskell can compete on those types of problems, it'll be easier to induce people to learn it. (Same with CL, my fav language....)

So here is a Scheme program that does this. It is written to use MzScheme because that's the only Scheme I have installed in Windows at the moment. Thus, it takes advantage of PLaneT and the other libraries that come with MzScheme.

Hopefully this can convince others that Scheme is a good language for common tasks.