Function: cl-labels

cl-labels is an autoloaded macro defined in cl-macs.el.gz.

Signature

(cl-labels ((FUNC ARGLIST BODY...) ...) FORM...)

Documentation

Make local (recursive) function definitions.

Each definition can take the form (FUNC EXP) where FUNC is the function name, and EXP is an expression that returns the function value to which it should be bound, or it can take the more common form (FUNC ARGLIST BODY...) which is a shorthand for (FUNC (lambda ARGLIST BODY)).

FUNC is defined in any BODY, as well as FORM, so you can write recursive and mutually recursive function definitions. See Info node
(cl) Function Bindings for details.

View in manual

Probably introduced at or before Emacs version 24.3.

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/cl-macs.el.gz
;;;###autoload
(defmacro cl-labels (bindings &rest body)
  "Make local (recursive) function definitions.

Each definition can take the form (FUNC EXP) where FUNC is the function
name, and EXP is an expression that returns the function value to which
it should be bound, or it can take the more common form (FUNC ARGLIST
BODY...) which is a shorthand for (FUNC (lambda ARGLIST BODY)).

FUNC is defined in any BODY, as well as FORM, so you can write recursive
and mutually recursive function definitions.  See Info node
`(cl) Function Bindings' for details.

\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
  (declare (indent 1) (debug cl-flet))
  (let ((binds ()) (newenv macroexpand-all-environment))
    (dolist (binding bindings)
      (let ((var (make-symbol (format "--cl-%s--" (car binding)))))
	(push (cons var (cdr binding)) binds)
	(push (cons (car binding)
                    (lambda (&rest args)
                      (if (eq (car args) cl--labels-magic)
                          (list cl--labels-magic var)
                        (cl-list* 'funcall var args))))
              newenv)))
    ;; Don't override lexical-let's macro-expander.
    (unless (assq 'function newenv)
      (push (cons 'function #'cl--labels-convert) newenv))
    ;; Perform self-tail call elimination.
    (setq binds (mapcar
                 (lambda (bind)
                   (pcase-let*
                       ((`(,var ,sargs . ,sbody) bind)
                        (`(function (lambda ,fargs . ,ebody))
                         (macroexpand-all `(cl-function (lambda ,sargs . ,sbody))
                                          newenv))
                        (`(,ofargs . ,obody)
                         (cl--self-tco var fargs ebody)))
                     `(,var (function (lambda ,ofargs . ,obody)))))
                 (nreverse binds)))
    `(letrec ,binds
       . ,(macroexp-unprogn
           (macroexpand-all
            (macroexp-progn body)
            newenv)))))