2 comments

[ 0.91 ms ] story [ 8.8 ms ] thread
Common Lisp does not have any built-ins for declaring static local variables known e.g. from C.

    int test_function() {
      static int counter = 0;
      return counter++;
    }
    
    test_function(); // -> 0
    test_function(); // -> 1
    test_function(); // -> 2
So, well, we can just implement them ourselves. It's Lisp, after all!

    (defun test-function ()
      (static-let ((counter 0))
        (incf counter)))
    
    (test-function) ; -> 1
    (test-function) ; -> 2
    (test-function) ; -> 3
This article is done in a literate programming style, attempting both to teach the basics of Lisp writing style and to describe the details of this static binding implementation.
In the TXR Lisp compiler load-time (what load-time-value is called: of course there is always a value, so why mention it) is used in the implementation of lambda hoisting.

E.g. if your compiler doesn't have lambda hoisting, you cna manually do it like this:

   (defun my-fun (...)
      (let ((fun (load-time (lambda (...))))
         ...))
This works if the function doesn't make any references to the lexical environment of the surrounding function. Then the lambda gets instantiated once and becomes a "virtual literal" in the loaded code; calls to my-fun no longer have to construct a closure; they just pull it out of the static data, where it is in a kind of fixed register at a known position.

The compiler has to recognize cases when this can be done automatically and make it so.