• Top
    • Documentation
    • Books
    • Recursion-and-induction
    • Boolean-reasoning
    • Debugging
    • Projects
    • Std
    • Proof-automation
    • Macro-libraries
    • ACL2
      • Theories
      • Rule-classes
      • Proof-builder
      • Hons-and-memoization
      • Events
      • History
      • Parallelism
      • Programming
        • Defun
        • Declare
        • System-utilities
        • Stobj
        • State
        • Memoize
        • Mbe
        • Io
        • Defpkg
        • Apply$
        • Mutual-recursion
        • Loop$
        • Programming-with-state
        • Arrays
        • Characters
        • Time$
        • Loop$-primer
        • Fast-alists
        • Defmacro
        • Defconst
        • Evaluation
        • Guard
        • Equality-variants
        • Compilation
        • Hons
        • ACL2-built-ins
        • System-attachments
        • Developers-guide
        • Advanced-features
        • Set-check-invariant-risk
        • Numbers
        • Irrelevant-formals
        • Efficiency
        • Introduction-to-programming-in-ACL2-for-those-who-know-lisp
        • Redefining-programs
        • Lists
        • Invariant-risk
        • Errors
        • Defabbrev
        • Conses
        • Alists
        • Set-register-invariant-risk
        • Strings
        • Program-wrapper
        • Get-internal-time
        • Basics
          • Let
          • Return-last
          • Mv-let
          • Or
          • Flet
          • Mv
          • And
          • Booleanp
          • If
          • Not
          • Equal
          • Implies
          • Iff
          • Quote
          • Macrolet
            • Let*
            • Case-match
            • ACL2-count
            • Good-bye
            • Case
            • Cond
            • Null
            • Progn$
            • Identity
            • Xor
          • Packages
          • Defmacro-untouchable
          • Primitive
          • <<
          • Revert-world
          • Set-duplicate-keys-action
          • Unmemoize
          • Symbols
          • Def-list-constructor
          • Easy-simplify-term
          • Defiteration
          • Defopen
          • Sleep
        • Start-here
        • Real
        • Debugging
        • Miscellaneous
        • Output-controls
        • Macros
        • Interfacing-tools
      • Interfacing-tools
      • Hardware-verification
      • Software-verification
      • Testing-utilities
      • Math
    • Basics
    • ACL2-built-ins

    Macrolet

    Local binding of macro symbols

    See flet for an analogous utility for defining functions locally.

    Example Form:
    (defun f1 (x)
      (macrolet ((mac (a) (list 'quote a)))
        (cons x (mac x))))

    The Example Form above is equivalent to the following, in which the call of local macro mac has been expanded.

    (defun f1-alt (x)
      (cons x (quote x)))

    The General Forms are similar to those of flet.

    General Forms:
    (macrolet (def1 ... defk) body)
    (macrolet (def1 ... defk) declare-form1 .. declare-formk body)

    where body is a term, and each defi is a definition as in defmacro but with the leading defmacro symbol omitted. See defmacro, but see declare for the declarations permitted directly under the defi. On the other hand, regarding the declare-formi (if any are supplied): each must be of the form (declare decl1 ... decln), where each decli is of the form (inline g1 ... gm) or (notinline g1 ... gm), and each gi is defined by some defi. Unlike the related utility flet, those inline and notinline declarations are unlikely to have any effect.

    The innermost flet or macrolet binding of a symbol, f, above a call of f, is the one that provides the definition of f for that call. Note that neither flet nor macrolet provide recursion: that is, the definition of f in an flet or macrolet binding of f is ignored in the body of that binding.

    The following requirements are imposed by Common Lisp and enforced by ACL2.

    • Every variable occurring in the body of a defi must be a formal parameter name of that defi.
    • No function or macro symbol called in the body of a defi may be defined by a superior flet or macrolet binding. (Not every Common Lisp implementation includes this restriction for superior macrolet bindings, but at least one (GCL) does so we include it in ACL2.)

    Although macrolet behaves in ACL2 essentially as it does in Common Lisp, ACL2 imposes the following restrictions and qualifications.

    • Every declare form for a local definition (def1 through defk, above) must be an ignore, ignorable, or type expression.
    • Each defi must bind a different symbol.
    • Each defi must bind a symbol that is a legal name for an ACL2 macro. In particular, the symbol may not be in the keyword package or the main Lisp package. Moreover, the symbol may not be a built-in ACL2 function or macro.

    Macrolet bindings are evaluated in parallel. Consider the following example.

    (defun f1 (x) (cons x 'x))
    (macrolet ((f1 (x) x)
               (f2 () (list 'quote
    ; The following reference is to the global f1,
    ; not to the identity macro just above.
                            (f1 3))))
      (f2))

    The macrolet form above evaluates to (3 . x), not to 3, as explained in the comment above. Here is a somewhat analogous form that one might expect to evaluate to 3, but that is not the case; see below.

    (macrolet ((f1 (x) x))
      (macrolet ((f2 () (list 'quote (f1 3))))
        (f2)))

    The body of f2 calls a symbol, f1, that is bound by a superior macrolet binding. As noted above, this is illegal (also for superior flet bindings).

    Under the hood, ACL2 expands away macrolet bindings. The following example illustrates this point.

    ACL2 !>:trans (macrolet ((mac (a) (list 'cons a a)))
                    (car (mac b)))
    
    (CAR (CONS B B))
    
    => *
    
    ACL2 !>

    Macrolet is part of Common Lisp. See any Common Lisp documentation for more information. We conclude by pointing out an important aspect of macrolet shared by ACL2 and Common Lisp: The binding is lexical, not dynamic. That is, the macrolet binding of a symbol only applies to calls of that symbol in the body of the macrolet, not other calls made in the course of evaluation. See flet for discussion of this point.