[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Closures in Emacs and their usage scenarios.

From: Hongyi Zhao
Subject: Re: Closures in Emacs and their usage scenarios.
Date: Tue, 28 Sep 2021 22:50:08 +0800

On Tue, Sep 28, 2021 at 7:53 PM Arthur Miller <> wrote:
> Stefan Monnier via Users list for the GNU Emacs text editor
> <> writes:
> >> I noticed the document on closure here [1] implemented in Emacs/Elisp 
> >> currently.
> >> But it's only a very concise and short introduction, and I want to
> >> know more about the closures in Emacs and their usage scenarios.
> >> Any helpful tips are welcome.
> >
> > Maybe a good starting point is
> >
> >
> Chapter 2 from "On Lisp" by P. Graham has also very nice and accessible intro 
> to
> functions and closures:
> So has also "Let Over Lambda" by D. Hoyte:
> Chapter 2 is an entire chapter on closures and using them; if one is not 
> scared
> by subtitles like: "Let Over Lambda Over Let Over Lambda" :).

I have excerpted all relevant discussions as follows from there [1]:

Let Over Lambda Over Let Over Lambda

Users of object systems store values they want shared between all
objects of a certain class into so-called class variables or static
variables8. In lisp, this concept of sharing state between closures is
handled by environments in the same way that closures themselves store
state. Since an environment is accessible indefinitely, as long as it
is still possible to reference it, we are guaranteed that it will be
available as long as is needed.

If we want to maintain a global direction for all counters, up to
increment each closure's counter and down to decrement, then we might
want to use a let over lambda over let over lambda pattern:

(let ((direction 'up))
  (defun toggle-counter-direction ()
    (setq direction
          (if (eq direction 'up)

  (defun counter-class ()
    (let ((counter 0))
      (lambda ()
        (if (eq direction 'up)
          (incf counter)
          (decf counter))))))

In the above example, we have extended counter-class from the previous
section. Now calling closures created with counter-class will either
increment its counter binding or decrement it, depending on the value
of the direction binding which is shared between all counters. Notice
that we also take advantage of another lambda inside the direction
environment by creating a function called toggle-counter-direction
which changes the current direction for all counters.

While this combination of let and lambda is so useful that other
languages have adopted it in the form of class or static variables,
there exist other combinations of let and lambda that allow you to
structure code and state in ways that don't have direct analogs in
object systems9. Object systems are a formalisation of a subset of let
and lambda combinations, sometimes with gimmicks like inheritance
bolted on10. Because of this, lisp programmers often don't think in
terms of classes and objects. Let and lambda are fundamental; objects
and classes are derivatives. As Steele says, the "object" need not be
a primitive notion in programming languages. Once assignable value
cells and good old lambda expressions are available, object systems
are, at best, occasionally useful abstractions and, at worst,
special-case and redundant.

But TBF, these contents are still not so easy for me to understand.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]