cl: Blocks and Exits

 
 4.5 Blocks and Exits
 ====================
 
 Common Lisp “blocks” provide a non-local exit mechanism very similar to
 ‘catch’ and ‘throw’, with lexical scoping.  This package actually
 implements ‘cl-block’ in terms of ‘catch’; however, the lexical scoping
 allows the byte-compiler to omit the costly ‘catch’ step if the body of
 the block does not actually ‘cl-return-from’ the block.
 
  -- Macro: cl-block name forms...
      The FORMS are evaluated as if by a ‘progn’.  However, if any of the
      FORMS execute ‘(cl-return-from NAME)’, they will jump out and
      return directly from the ‘cl-block’ form.  The ‘cl-block’ returns
      the result of the last FORM unless a ‘cl-return-from’ occurs.
 
      The ‘cl-block’/‘cl-return-from’ mechanism is quite similar to the
      ‘catch’/‘throw’ mechanism.  The main differences are that block
      NAMEs are unevaluated symbols, rather than forms (such as quoted
      symbols) that evaluate to a tag at run-time; and also that blocks
      are always lexically scoped.  In a dynamically scoped ‘catch’,
      functions called from the ‘catch’ body can also ‘throw’ to the
      ‘catch’.  This is not an option for ‘cl-block’, where the
      ‘cl-return-from’ referring to a block name must appear physically
      within the FORMS that make up the body of the block.  They may not
      appear within other called functions, although they may appear
      within macro expansions or ‘lambda’s in the body.  Block names and
      ‘catch’ names form independent name-spaces.
 
      In true Common Lisp, ‘defun’ and ‘defmacro’ surround the function
      or expander bodies with implicit blocks with the same name as the
      function or macro.  This does not occur in Emacs Lisp, but this
      package provides ‘cl-defun’ and ‘cl-defmacro’ forms, which do
      create the implicit block.
 
      The Common Lisp looping constructs defined by this package, such as
      ‘cl-loop’ and ‘cl-dolist’, also create implicit blocks just as in
      Common Lisp.
 
      Because they are implemented in terms of Emacs Lisp’s ‘catch’ and
      ‘throw’, blocks have the same overhead as actual ‘catch’ constructs
      (roughly two function calls).  However, the byte compiler will
      optimize away the ‘catch’ if the block does not in fact contain any
      ‘cl-return’ or ‘cl-return-from’ calls that jump to it.  This means
      that ‘cl-do’ loops and ‘cl-defun’ functions that don’t use
      ‘cl-return’ don’t pay the overhead to support it.
 
  -- Macro: cl-return-from name [result]
      This macro returns from the block named NAME, which must be an
      (unevaluated) symbol.  If a RESULT form is specified, it is
      evaluated to produce the result returned from the ‘block’.
      Otherwise, ‘nil’ is returned.
 
  -- Macro: cl-return [result]
      This macro is exactly like ‘(cl-return-from nil RESULT)’.  Common
      Lisp loops like ‘cl-do’ and ‘cl-dolist’ implicitly enclose
      themselves in ‘nil’ blocks.
 
  -- Macro: cl-tagbody &rest labels-or-statements
      This macro executes statements while allowing for control transfer
      to user-defined labels.  Each element of LABELS-OR-STATEMENTS can
      be either a label (an integer or a symbol), or a cons-cell (a
      statement).  This distinction is made before macroexpansion.
      Statements are executed in sequence, discarding any return value.
      Any statement can transfer control at any time to the statements
      that follow one of the labels with the special form ‘(go LABEL)’.
      Labels have lexical scope and dynamic extent.