• 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
        • Apply$
        • Defpkg
        • Mutual-recursion
        • Loop$
        • Programming-with-state
        • Arrays
        • Characters
        • Time$
        • Loop$-primer
        • Fast-alists
          • Slow-alist-warning
          • Hons-acons
          • Fast-alist-fork
          • Hons-acons!
          • With-fast-alist
            • Fast-alist-clean
            • Fast-alist-pop
            • Fast-alist-free
            • Fast-alist-pop*
            • Hons-get
            • Hons-assoc-equal
            • Make-fast-alist
            • Make-fal
            • Fast-alist-free-on-exit
            • With-stolen-alist
            • Fast-alist-fork!
            • Fast-alist-summary
            • Fast-alist-clean!
            • Fast-alist-len
            • With-stolen-alists
            • Fast-alists-free-on-exit
            • Cons-subtrees
            • With-fast-alists
            • Hons-dups-p1
            • Ansfl
            • Hons-revappend
            • Hons-member-equal
            • Hons-make-list
            • Hons-reverse
            • Hons-list*
            • Hons-list
            • Hons-append
          • Defmacro
          • Defconst
          • Evaluation
          • Guard
          • Equality-variants
          • Compilation
          • Hons
          • ACL2-built-ins
          • Developers-guide
          • System-attachments
          • 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
          • 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
    • Fast-alists
    • ACL2-built-ins

    With-fast-alist

    (with-fast-alist name form) causes name to be a fast alist for the execution of form.

    Logically, with-fast-alist just returns form.

    Under the hood, we cause alist to become a fast alist before executing form. If doing so caused us to introduce a new hash table, the hash table is automatically freed after form completes.

    More accurately, under the hood (with-fast-alist name form) essentially expands to something like:

    (if (already-fast-alist-p name)
        form
      (let ((<temp> (make-fast-alist name)))
        (prog1 form
               (fast-alist-free <temp>))))

    Practically speaking, with-fast-alist is frequently a better choice then just using make-fast-alist, and is particularly useful for writing functions that can take either fast or slow alists as arguments. That is, consider the difference between:

    (defun bad (alist ...)
      (let* ((fast-alist (make-fast-alist alist))
             (answer     (expensive-computation fast-alist ...)))
       (prog2$ (fast-alist-free fast-alist)
               answer)))
    
    (defun good (alist ...)
       (with-fast-alist alist
         (expensive-computation alist ...)))

    Either approach is fine if the caller provides a slow alist. But if the input alist is already fast, bad will (perhaps unexpectedly) free it! On the other hand, good is able to take advantage of an already-fast argument and will not cause it to be inadvertently freed.

    See also the macro with-fast-alists defined in the community book "books/centaur/misc/hons-extra.lisp", which allows you to call with-fast-alist on several alists simultaneously.

    The community book "books/centaur/misc/hons-extra.lisp" extends the b* macro with the with-fast pattern binder. That is, after executing (include-book "centaur/misc/hons-extra.lisp" :dir :system) you may write something like this:

    (b* (...
         ((with-fast a b c ...))
         ...)
      ...)

    which causes a, b, and c to become fast alists until the completion of the b* form.

    Note that with-fast-alist will cause logically tail-recursive functions not to execute tail-recursively if its cleanup phase happens after the tail-recursive call returns.