Static-Let, or how I Learned to stop worrying and love Load-Time-Value
github.com
github.com
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.
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.