Frank Shearar
Frank Shearar

Reputation: 17132

DEFUNs inside a LET - why?

I was reading the source for ChanL the other day. It contains an example use of channels, to implement futures. The DEFUNs were declared inside a LET, like so:

(let ((some-var some-value))
  (defun foo () ... (reference some-var) ... )
  (defun bar () ...))

What purpose does this serve? Is it just to provide some common value that several functions can share, and keep the encapsulation clean?

Upvotes: 2

Views: 1270

Answers (2)

mihai
mihai

Reputation: 4722

Those are just closures. Just for the historical context [1],

Closures play a more conspicuous role in a style of programming promoted by Abelson and Sussman’s classic Structure and Interpretation of Computer Programs. Closures are functions with local state. The simplest way to use this state is in a situation like the following:

(let ((counter 0))
  (defun new-id () (incf counter))
  (defun reset-id () (setq counter 0)))

These two functions share a variable which serves as a counter. The first one returns successive values of the counter, and the second resets the counter to 0. The same thing could be done by making the counter a global variable, but this way it is protected from unintended references.

Paul Graham - On lisp

Upvotes: 2

koddo
koddo

Reputation: 3408

You already answered your question: to provide shared bindings for a group of functions and keep encapsulation clean.

Simple example from http://letoverlambda.com/textmode.cl/guest/chap2.html:

(let ((direction 'down))
  (defun toggle-direction ()
    (setq direction
          (if (eq direction 'up)
              'down
              'up))))
(toggle-direction)   => UP
(toggle-direction)   => DOWN
(toggle-direction)   => UP
(toggle-direction)   => DOWN

You can also add a function inside this closure which behavior depends on direction.

Upvotes: 6

Related Questions