cl: Declarations

 
 6 Declarations
 **************
 
 Common Lisp includes a complex and powerful “declaration” mechanism that
 allows you to give the compiler special hints about the types of data
 that will be stored in particular variables, and about the ways those
 variables and functions will be used.  This package defines versions of
 all the Common Lisp declaration forms: ‘declare’, ‘locally’, ‘proclaim’,
 ‘declaim’, and ‘the’.
 
    Most of the Common Lisp declarations are not currently useful in
 Emacs Lisp.  For example, the byte-code system provides little
 opportunity to benefit from type information.  A few declarations are
 meaningful when byte compiler optimizations are enabled, as they are by
 the default.  Otherwise these declarations will effectively be ignored.
 
  -- Function: cl-proclaim decl-spec
      This function records a “global” declaration specified by
      DECL-SPEC.  Since ‘cl-proclaim’ is a function, DECL-SPEC is
      evaluated and thus should normally be quoted.
 
  -- Macro: cl-declaim decl-specs...
      This macro is like ‘cl-proclaim’, except that it takes any number
      of DECL-SPEC arguments, and the arguments are unevaluated and
      unquoted.  The ‘cl-declaim’ macro also puts ‘(cl-eval-when (compile
      load eval) ...)’ around the declarations so that they will be
      registered at compile-time as well as at run-time.  (This is vital,
      since normally the declarations are meant to influence the way the
      compiler treats the rest of the file that contains the ‘cl-declaim’
      form.)
 
  -- Macro: cl-declare decl-specs...
      This macro is used to make declarations within functions and other
      code.  Common Lisp allows declarations in various locations,
      generally at the beginning of any of the many “implicit ‘progn’s”
      throughout Lisp syntax, such as function bodies, ‘let’ bodies, etc.
      Currently the only declaration understood by ‘cl-declare’ is
      ‘special’.
 
  -- Macro: cl-locally declarations... forms...
      In this package, ‘cl-locally’ is no different from ‘progn’.
 
  -- Macro: cl-the type form
      ‘cl-the’ returns the value of ‘form’, first checking (if
      optimization settings permit) that it is of type ‘type’.  Future
      byte-compiler optimizations may also make use of this information
      to improve runtime efficiency.
 
      For example, ‘mapcar’ can map over both lists and arrays.  It is
      hard for the compiler to expand ‘mapcar’ into an in-line loop
      unless it knows whether the sequence will be a list or an array
      ahead of time.  With ‘(mapcar 'car (cl-the vector foo))’, a future
      compiler would have enough information to expand the loop in-line.
      For now, Emacs Lisp will treat the above code as exactly equivalent
      to ‘(mapcar 'car foo)’.
 
    Each DECL-SPEC in a ‘cl-proclaim’, ‘cl-declaim’, or ‘cl-declare’
 should be a list beginning with a symbol that says what kind of
 declaration it is.  This package currently understands ‘special’,
 ‘inline’, ‘notinline’, ‘optimize’, and ‘warn’ declarations.  (The ‘warn’
 declaration is an extension of standard Common Lisp.)  Other Common Lisp
 declarations, such as ‘type’ and ‘ftype’, are silently ignored.
 
 ‘special’
      Since all variables in Emacs Lisp are “special” (in the Common Lisp
      sense), ‘special’ declarations are only advisory.  They simply tell
      the byte compiler that the specified variables are intentionally
      being referred to without being bound in the body of the function.
      The compiler normally emits warnings for such references, since
      they could be typographical errors for references to local
      variables.
 
      The declaration ‘(cl-declare (special VAR1 VAR2))’ is equivalent to
      ‘(defvar VAR1) (defvar VAR2)’.
 
      In top-level contexts, it is generally better to write ‘(defvar
      VAR)’ than ‘(cl-declaim (special VAR))’, since ‘defvar’ makes your
      intentions clearer.
 
 ‘inline’
      The ‘inline’ DECL-SPEC lists one or more functions whose bodies
      should be expanded “in-line” into calling functions whenever the
      compiler is able to arrange for it.  For example, the function
      ‘cl-acons’ is declared ‘inline’ by this package so that the form
      ‘(cl-acons KEY VALUE ALIST)’ will expand directly into ‘(cons (cons
      KEY VALUE) ALIST)’ when it is called in user functions, so as to
      save function calls.
 
      The following declarations are all equivalent.  Note that the
      ‘defsubst’ form is a convenient way to define a function and
      declare it inline all at once.
 
           (cl-declaim (inline foo bar))
           (cl-eval-when (compile load eval)
             (cl-proclaim '(inline foo bar)))
           (defsubst foo (...) ...)       ; instead of defun
 
      *Please note:* this declaration remains in effect after the
      containing source file is done.  It is correct to use it to request
      that a function you have defined should be inlined, but it is
      impolite to use it to request inlining of an external function.
 
      In Common Lisp, it is possible to use ‘(declare (inline ...))’
      before a particular call to a function to cause just that call to
      be inlined; the current byte compilers provide no way to implement
      this, so ‘(cl-declare (inline ...))’ is currently ignored by this
      package.
 
 ‘notinline’
      The ‘notinline’ declaration lists functions which should not be
      inlined after all; it cancels a previous ‘inline’ declaration.
 
 ‘optimize’
      This declaration controls how much optimization is performed by the
      compiler.
 
      The word ‘optimize’ is followed by any number of lists like ‘(speed
      3)’ or ‘(safety 2)’.  Common Lisp defines several optimization
      “qualities”; this package ignores all but ‘speed’ and ‘safety’.
      The value of a quality should be an integer from 0 to 3, with 0
      meaning “unimportant” and 3 meaning “very important”.  The default
      level for both qualities is 1.
 
      In this package, the ‘speed’ quality is tied to the ‘byte-optimize’
      flag, which is set to ‘nil’ for ‘(speed 0)’ and to ‘t’ for higher
      settings; and the ‘safety’ quality is tied to the
      ‘byte-compile-delete-errors’ flag, which is set to ‘nil’ for
      ‘(safety 3)’ and to ‘t’ for all lower settings.  (The latter flag
      controls whether the compiler is allowed to optimize out code whose
      only side-effect could be to signal an error, e.g., rewriting
      ‘(progn foo bar)’ to ‘bar’ when it is not known whether ‘foo’ will
      be bound at run-time.)
 
      Note that even compiling with ‘(safety 0)’, the Emacs byte-code
      system provides sufficient checking to prevent real harm from being
      done.  For example, barring serious bugs in Emacs itself, Emacs
      will not crash with a segmentation fault just because of an error
      in a fully-optimized Lisp program.
 
      The ‘optimize’ declaration is normally used in a top-level
      ‘cl-proclaim’ or ‘cl-declaim’ in a file; Common Lisp allows it to
      be used with ‘declare’ to set the level of optimization locally for
      a given form, but this will not work correctly with the current
      byte-compiler.  (The ‘cl-declare’ will set the new optimization
      level, but that level will not automatically be unset after the
      enclosing form is done.)
 
 ‘warn’
      This declaration controls what sorts of warnings are generated by
      the byte compiler.  The word ‘warn’ is followed by any number of
      “warning qualities”, similar in form to optimization qualities.
      The currently supported warning types are ‘redefine’, ‘callargs’,
      ‘unresolved’, and ‘free-vars’; in the current system, a value of 0
      will disable these warnings and any higher value will enable them.
      See the documentation of the variable ‘byte-compile-warnings’ for
      more details.