* A condition system for T -*- outline -*- ### This document is out of date. The file CONDITION.T has changed ### ### without the common decency to inform this document. Apologies. ### This document describes the condition system that will be implemented in T4. Its general design is based on that of Common Lisp in that it partitions the signalling, handling, and recovering of exceptional situations. Elements of its design were based on discussions on the rrrs-authors mailing list about condition systems for Scheme. The bulk of the design is entirely original, however, in its use of T operations and generic objects. ** Definitions: condition - an object that describes an exceptional situation; on it several operations related to the condition system are usually defined, such as CONDITION-RESTARTERS & DEFAULT-CONDITION-HANDLER. condition handler - a procedure of one argument meant to handle an exceptional situation; it is passed the condition that describes the exceptional situation; it is active if present in the condition handler stack condition handler stack - a stack of condition handlers, part of the dynamic environment, to which elements can be pushed for a dynamic extent using WITH-CONDITION-HANDLER; the first element is the current condition handler current condition handler - the most recently installed condition handler; the car of the condition handler stack handler - the body of code that handles a condition restarter - an object that describes a protocol for restarting a computation after an exceptional situation was encountered signaller - the body of code that signals a condition due to an exceptional situation ** Core procedure listing These are all of the procedures truly at the core of the condition system. Others can be easily defined in terms of them. This listing exists to show how simple the core of the system is. The rest is useful taxonomy and conveniences. Handling & signalling SIGNAL-CONDITION WITH-CONDITION-HANDLER Conditions CONDITION? CONDITION-RESTARTERS DEFAULT-CONDITION-HANDLER SERIOUS-CONDITION? STANDARD-SERIOUS-CONDITION-HANDLER Restarters RESTARTER? BOUND-RESTARTERS WITH-RESTARTER INTERACTIVE-RESTARTER? RESTART-INTERACTIVELY ** Signalling and handling conditions When an exceptional situation is encountered in a T program, it may /signal a condition/ by calling the procedure SIGNAL-CONDITION with one argument, the condition. This invokes the current condition handler on that condition in a dynamic environment in which the condition handler stack was that when the current condition handler was installed, but that is otherwise exactly the same as the dynamic environment of the signaller. (It is therefore safe to signal a condition from within a handler and not be caught in an infinite loop of a handler signalling to itself.) The handler typically chooses one of three options, though it is free to process the condition in any manner: * It may /decline/ to handle the condition. It does this by simply returning the condition (or any object), which is then propagated up to the next most recently installed condition handler. * It may /exit/ by performing a non-local exit through calling an escape procedure to some enclosing context. * It may /restart/ by invoking a restarter (see below on restarting). Condition handlers cannot simply return to the signaller. If a condition handler returns normally, the object that it returns is automatically passed on to the next dynamically enclosing handler. If the outermost handler declines the condition, the /default handler/ of the final condition (which may or may not be the same as the original condition passed to SIGNAL-CONDITION) is called. The default handler may return normally to the site of the signaller: control may return to the signaller only by the default handler or by invoking a restarter. Note that only a constant amount of stack space is ever accumulated between the signaller and the condition handler by SIGNAL-CONDITION, though it is not zero space; that is, the call to the condition handler is a non-tail call, but the loop to call successive elements of the condition handler stack is guaranteed to be properly tail recursive. (SIGNAL-CONDITION condition) -> values (may not return) ;procedure Signals CONDITION by invoking the stack of handlers one by one. (SIGNAL-IGNORABLY condition) -> values (may not return) ;procedure Similar to SIGNAL-CONDITION, but first establishes an IGNORE restarter that will return to the call to SIGNAL-IGNORABLY if invoked, and the restarter is appended to CONDITION's restarter list, as if with (MODIFY-CONDITION-RESTARTERS CONDITION (LAMBDA (RS) (APPEND RS (LIST R)))), where R is the new IGNORE restarter. Invoked interactively, the restarter has the same effect as a non-interactive invocation. (WITH-CONDITION-HANDLER handler thunk) -> values ;procedure Pushes HANDLER onto the stack of condition handlers for the dynamic extent of THUNK. If THUNK returns normally, WITH-CONDITION-HANDLER returns the values it returned. There are also two conveniences for common idioms for handlers: (WITH-EXITING-CONDITION-HANDLER handler thunk) -> values ;procedure This is similar to WITH-CONDITION-HANDLER, but HANDLER is called after exiting out to the dynamic context that was in place when WITH-EXITING-CONDITION-HANDLER was initially called, as if it were a tail call in the place of WITH-EXITING-CONDITION-HANDLER. HANDLER may therefore return as if from WITH-EXITING-CONDITION-HANDLER. If THUNK returns normally, this returns the values that THUNK returned. (TRAP-ERRORS thunk) -> condition or values ;procedure Calls THUNK; if an error is signalled in the dynamic extent of THUNK or propagated upward from an inner condition handler, the condition is trapped and returned from the call to TRAP-ERRORS. Non-error conditions are propagated up to the next dynamically enclosing handler. If no error is signalled, TRAP-ERRORS returns the values that THUNK returns. (IGNORE-CONDITIONS thunk) -> values ;procedure Calls THUNK; if any condition is signalled during its dynamic extent that has an associated IGNORE restarter, that restarter is invoked. Any other conditions are propagated up to the next dynamically enclosing handler. (IGNORE-CONDITIONS-IF pred thunk) -> values ;procedure Like IGNORE-CONDITIONS, but restarts only if the signalled conditions not only have associated IGNORE restarters but also satisfy PRED. PRED is called only on conditions that have IGNORE restarters. For example, to muffle warning messages in a body of code, one might (IGNORE-CONDITIONS-IF WARNING? (LAMBDA () body)). ** Conditions Conditions are objects that represent exceptional situations. There is no particular representation imposed on them; they are simply expected to have certain operations defined on them and answer true to certain predicates. (CONDITION? object) -> boolean ;predicate Returns true if OBJECT is considered a condition. All objects used to represent exceptional situations should answer true to CONDITION?. (CONDITION-RESTARTERS condition) -> restarter list ;operation Returns the list of restarters by which the exceptional situation that CONDITION describes can be restarted. Conditions are not obligated to handle this operation; the default method simply returns the empty list. (MODIFY-CONDITION-RESTARTERS condition proc) -> condition ;procedure Returns a condition that is equivalent to CONDITION in every way except the associated restarter list, which is produced in the new condition by passing CONDITION's restarter list to PROC. PROC is called once by MODIFY-CONDITION-RESTARTERS; it is not called every time CONDITION-RESTARTERS is applied to the resulting condition. MODIFY-CONDITION-RESTARTERS does not destructively modify CONDITION. (DEFAULT-CONDITION-HANDLER condition) ;operation Returns a unary procedure that performs the default handler operation of CONDITION. When SIGNAL-CONDITION is invoked with a condition, it obtains that condition's default handler, and stores it for later. If all of the dynamically bound condition handlers decline to handle the condition, the saved default handler is invoked on the condition that the last handler returned. (Note that this may not be the same condition that was passed to DEFAULT-CONDITION-HANDLER.) Default condition handlers will typically either simply return to the signaller (which dynamically bound condition handlers cannot, without explicitly invoking a restarter), display a messsage and return to the signaller, or invoke some sort of debugger. The default default handler (i.e. the default handler for any conditions on which the DEFAULT-CONDITION-HANDLER operation is undefined) for non-serious conditions simply returns an unspecified result to the signaller, while for serious conditions the default serious condition handler hook, as it was when the condition was signalled (so dynamically bound handlers can have no effect on it), is invoked on the condition. (JOIN-CONDITIONS displayer cond0 cond1 ...) -> condition ;procedure Returns a condition CONDJ that is like (JOIN cond0 cond1 ...), but such that (CONDITION-RESTARTERS condJ) will return a list of all of the restarters of all of the conditions supplied, in the order that they were supplied; and (DISPLAY condJ port) will display a message based on DISPLAYER: if it is a string, it will simply be written to PORT surrounded by fresh lines; if it is a two-argument procedure, it will be applied to CONDJ & PORT, in that argument order. (An error is signalled if DISPLAYER is neither a string nor a procedure.) *** Guidelines for displaying conditions By convention, the DISPLAY operation is defined on conditions to display human-readable messages of a condition of the following form: 1. The message should begin on a fresh line. 2. The entire message usually has some prefix. If the condition is not serious, it usually begins with a prefix; if the condition is important and related to a potential problem in operation, the prefix should also have two asterisks. For instance, notes are displayed with a prefix of ";", warnings are displayed with a prefix of ";** ", and errors are displayed with a prefix of "** ". 3. The message should begin with a /condition type string/ followed by a colon and a space. For instance, the first line of a note will usually begin with ";Note: "; of a warning, ";** Warning: "; and of an error, "** Error: ". 4. An initial description should be displayed. It should give a brief overview of the error, and it should be neither capitalized nor followed by a period. For instance, if an error is signalled because an attempt was made to evaluate a reference to an unbound variable, the description might be "reference to unbound variable" or simply "unbound variable". 5. Finally, anything else pertaining to the condition should be displayed on following lines with spaces after the prefix equal in number to the number of characters in the type string plus two (to account for the colon and space following the type string.) That is, the text on every following line should begin on the same column as that on which the initial description string began. 6. A newline should be printed at the end of the message. For a complete example, here is how an argument type mismatch error might be displayed: ** Error: wrong type argument ** FROBBOTZIM ** as operand 0 of CAR ** expected pair Here is how a warning condition might be displayed: ;** Warning: discarding extraneous closing parenthesis ;** #{Port STANDARD-INPUT 123} (STANDARD-DISPLAY-CONDITION port prefix type fmt args) ;procedure Displays output in the form described in the above guidelines. FMT is a format control string, in the sense of FORMAT, to which ARGS is supplied as arguments. A fresh line is printed before the message, followed by the prefix, type, and colon. Then the format string is displayed. Every newline in the format string, i.e. ~% directive, causes a newline, prefix, and number of spaces to be displayed before any text due to the format string. After the end of the formatted output, a newline is written. For instance, (STANDARD-DISPLAY-CONDITION (STANDARD-OUTPUT) "** " "Error" '("wrong type argument~%" "~S~%" "expected a pair") (LIST PAIR)) would print as this, assuming that PAIR is the vector #(A B C): ** Error: wrong type argument ** #(A B C) ** expected a pair (Note that the format string does _not_ need to insert the prefix and spaces itself, unlike in the original T error system. This allows for the format strings to be more readable and it does not force them to be specific to the prefix of one particular type of error.) Finally, note that these are only guidelines. They may be broken if appropriate; for instance, Orbit may display warnings like this: ;** Warning: unreferenced variable FOO ; Location: in definition of BAR or statically provable semantic errors like this: ;** Error: wrong number of arguments in a call to (LAMBDA (Z) ...) ; Action: replacing with undefined effect ; Location: in definition of FNORD *** Condition taxonomy The condition system also provides a rich taxonomy for a variety of different types of conditions. There are two main classes of conditions: serious conditions and non-serious conditions. Serious conditions are treated specially by some system procedures; e.g., if a condition that all handlers decline is serious (in the sense of the predicate SERIOUS-CONDITION?), and it does not have a default handler, the /standard serious condition handler/ is called instead. This typically either invokes a debugger of some sort or exits the T system. Notes & warnings are not serious, while errors are. (Not all serious conditions are errors, however.) (SERIOUS-CONDITION? condition) -> boolean ;predicate (STANDARD-SERIOUS-CONDITION-HANDLER) -> procedure ;settable SERIOUS-CONDITION? is the predicate to which all serious conditions answer true. STANDARD-SERIOUS-CONDITION-HANDLER returns the standard serious condition handler procedure, which may be set using (SET (STANDARD-SERIOUS-CONDITION-HANDLER) ...). The standard serious condition handler should be a procedure of one argument, the serious condition, that does not return. **** Note conditions Note conditions are intended for unimportant notes about a program's operation, not of enough significance to be warnings or considered serious. (NOTE? obj) -> boolean ;predicate (NOTE format-string argument ...) -> values ;procedure NOTE signals a condition that answers true to NOTE? and has no default handler, so NOTE will simply return an unspecified result, as the default default condition handler (see DEFAULT-CONDITION-HANDLER) will do, if the condition is unhandled. For the note to be displayed to a user, a condition handler must explicitly call DISPLAY; note conditions are displayed following the guidelines in the section on displaying conditions, with a prefix of a semicolon and a type string of "Note". E.g., the condition signalled by (NOTE "closing garbage- collected port~%~S" PORT) might be displayed as ;Note: closing garbage-collected port ; #{Port FROBOZZ 123} NOTE also establishes an IGNORE restarter, before signalling the condition, that accepts zero arguments and throws back to the call to NOTE. Interactively, it does the same. The restarter is included in the condition's restarter list, as obtained by CONDITION-RESTARTERS. **** Warning conditions Warnings are meant to describe inconsistencies or non-serious problems in a program's operation that are of enough significance to warrant a message usually being displayed somewhere. The functional difference between warnings and notes is that the default condition handler for warnings signalled by WARNING will usually print the warning (depending on the value of STANDARD-WARNING-HANDLER), whereas the default handler for notes signalled by NOTE does nothing. (WARNING? obj) -> boolean ;predicate (WARNING format-string argument ...) -> values ;procedure (STANDARD-WARNING-HANDLER) -> procedure ;settable procedure WARNING signals a condition that answers true to WARNING? and whose default handler calls the standard warning handler, a simple hook accessed with (STANDARD-WARNING-HANDLER) and modified by using (SET (STANDARD-WARNING-HANDLER) ...), whose default value is a procedure that displays the condition to the current terminal output port and returns an unspecified result to the signaller. The warning is displayed as a message in the form described by the guidelines in the section on displaying conditions, with a prefix of ";** " and a condition type string of "Warning". For example, the warning that (WARNING "discarding extraneous closing parenthesis~%~S" PORT) signals might be displayed as: ;** Warning: discarding extraneous closing parenthesis ;** #{Port FOOBAR 123} WARNING also establishes an IGNORE restarter, before signalling the condition, that accepts zero arguments and simply throws back to the call to WARNING. Interactively, the restarter does the same. The restarter is included in the condition's restarter list, as obtained with CONDITION-RESTARTERS. **** Errors Errors are semantic inconsistencies in a program's operation, such as an inapplicable datum being called, an object of the wrong type being passed to a procedure, &c. All errors are serious conditions, i.e. they must answer true to SERIOUS-CONDITION?, and they must additionally answer true to the ERROR? predicate. (ERROR? obj) -> boolean ;predicate (ERROR format-string argument ...) -> does not return ;procedure (IGNORABLE-ERROR displayer format-string argument ...) ;procedure -> zero values (MAKE-SIMPLE-ERROR restarters type-prefix format args) ;procedure ERROR? is the predicate for error conditions. ERROR signals an error condition. Its DISPLAY method will show message in a form described by the guidelines in the section on displaying conditions, with a prefix of "** " and a type string of "Error". For instance, (ERROR "illegal number~%~S" N) might be displayed as ** Error: illegal number ** #{Fnord 123} IGNORABLE-ERROR is like ERROR, but it also establishes a IGNORE restarter that simply returns zero values to the IGNORABLE-ERROR call, non-interactively or interactively, and whose DISPLAY method calls DISPLAYER. MAKE-SIMPLE-ERROR is a general constructor for error conditions with any list of restarters and condition type string. Note that the format string arguments are given as a list, not as rest arguments, as they are in ERROR & IGNORABLE-ERROR. For instance, ERROR and IGNORABLE-ERROR are trivially defined in terms of MAKE-SIMPLE-ERROR: (define (error fmt . args) (signal-condition (make-simple-error '() "Error" fmt args))) (define (ignorable-error displayer fmt . args) (with-exiting-restarter restart/ignore? 'ignore displayer (lambda (r) (signal-condition (make-simple-error (list r) "Error" fmt args))))) Many error conditions are signalled with more specialized information than a simple human-readable message. In the most common example of this, a datum was malformed or used in an illegal context, for which purpose /datum errors/ exist. (DATUM-ERROR? condition) -> boolean (ERROR-DATUM condition) -> object (MAKE-DATUM-ERROR datum restarters type-prefix fmt args) ;procedure DATUM-ERROR? is the predicate for conditions with an associate datum. ERROR-DATUM accesses the datum of such conditions. MAKE-DATUM-ERROR constructs a datum error with the given datum, like MAKE-SIMPLE-ERROR does with simple errors. ;;; Substitutability of datum errors is a problem that needs to be ;;; worked on. Previously, SYNTAX-ERROR & SUBSTITUTABLE-SYNTAX-ERROR ;;; were described here, but internally there were also two procedures ;;; WRONG-TYPE-ARGUMENT-ERROR & ARGUMENT-OUT-OF-RANGE-ERROR, which can ;;; both reasonably be used substitutably and non-substitutably; ;;; however, SUBSTITUTABLE-ARGUMENT-OUT-OF-RANGE-ERROR is a *bit* of a ;;; mouthful, and it seems kludgey to just make ad-hoc SUBSTITUTABLE- ;;; variants of the relevant procedures. ** Restarting One of the most important aspects of an effective condition system is a protocol for /restarting/ computations that signalled conditions. T T provides a /restarter/ abstraction for encapsulating the information necessary for a handler to restart computation near the signaller without requiring hacks intrusive to abstractions, such as support in the debugger for manually restarting individual call frames (which is useful, but inapplicable for large systems in which separate components must interact gracefully when conditions occur across boundaries of modules and abstractions). /Restarters/ are applicable objects that are usually either /bound/ or /associated with a condition/. If bound, a restarter is in the /bound restarters list/; if associated with a condition, a restarter is in the list that CONDITION-RESTARTERS returns when passed that condition. (A restarter may be both bound and associated with arbitrarily many conditions.) To invoke a restarter, possibly with some arguments, it can be simply applied as a procedure. Restarters may furthermore be interactive, which means that they provide a way to be interactively invoked by some user, often after receiving input from the user. Restarters are invoked interactively with RESTART-INTERACTIVELY. Restarters of different varieties are discerned by simply answering true to different predicates. This is similar to Common Lisp's use of symbols to distinguish different types of restarts or Dylan's use of classes. For example, restarters intended to retry computations with a replacement input value answer true to RESTART/USE-VALUE?. There is a complete listing of the different built-in restarter types below. Interactive restarters should be able to be displayed using DISPLAY. Their DISPLAY methods should print a brief one-line synopsis of the manner in which they restart a computation. The line should not be preceded or followed by newline characters, and it should be a complete sentence, capitalized and with a period at the end, in the imperative. Here are some examples of such descriptions: Exit the REPL. Return to the top level. Use a different value. Return to REPL level 1. Ignore the warning. Many of the following procedures accept a RESTARTERS argument. There are several possible forms that this argument may have, which are listed here along with their meaning: - A list of restarters. This is used literally. - The true constant #T. The bound restarters are used. - An object for which CONDITION-RESTARTERS returns a list, which is used for the purpose. Anything else is an error. (RESTARTER? obj) -> boolean ;predicate (BOUND-RESTARTERS) -> restarter list ;procedure RESTARTER? is the predicate for restarter objects; all objects used as restarters must answer true to this predicate. BOUND-RESTARTERS returns a freshly allocated list of all currently bound restarters. (INTERACTIVE-RESTARTER? obj) -> boolean ;predicate (RESTART-INTERACTIVELY restarter) -> does not return ;operation INTERACTIVE-RESTARTER? is the predicate for restarters that may be interactively invoked. RESTART-INTERACTIVELY invokes RESTARTER interactively. This usually means reading input from a user after printing a prompt and then restarting by applying RESTARTER with the input read. (FIND-RESTARTER pred [restarters]) -> restarter or #F ;procedure (SELECT-RESTARTERS pred [restarters]) -> restarter list ;procedure (INTERACTIVE-RESTARTERS [restarters]) -> restarter list ;procedure (NAMED-RESTARTERS names [restarters]) -> restarter list ;procedure FIND-RESTARTER returns the first restarter in the list RESTARTERS, whose default value is the bound restarter list, that answers true to PRED, or #F if there is no restarter satisfying PRED in that list. SELECT-RESTARTERS returns a list of all restarters in RESTARTERS, whose default value is the list of bound restarters, that satisfy PRED. INTERACTIVE-RESTARTERS is equivalent to (SELECT-RESTARTERS INTERACTIVE-RESTARTER? restarters). NAMED-RESTARTERS returns a list of each restarter R in RESTARTERS, whose default value is again the list of bound restarters, such that (IDENTIFICATION r) is, if NAMES is a symbol, identical to NAMES in terms of EQ?; or, if NAMES is a list, a member of the list NAMES in terms of MEMQ?. It is an error for NAMES to have any other form. (WITH-RESTARTER restarter thunk) -> values ;procedure Calls THUNK, for whose dynamic extent RESTARTER is added to the front of the bound restarter list. *** Common restarters This section describes several common idioms for restarters as well as a list of standard restarter predicates and finders. In this section, many procedures accept a DISPLAYER argument. This argument may be a procedure, in which case it is called when a resultant reestarter is passed to DISPLAY, or a string, in which case it is written verbatim when the resultant restarter is passed to DISPLAY. Exiting restarters just return zero values to a continuation to exit. They are interactive, too; invoking them interactively is equivalent to invoking them non-interactively. They answer true to a predicate given to the procedure that created them, not to any EXITING-RESTARTER? procedure or anything. (It is useful to install both ABORT & IGNORE restarters as simple restarters, for instance, which have the same interface but serve different purposes and answer true to different predicates.) (MAKE-EXITING-RESTARTER throw pred id displayer) ;procedure -> restarter (WITH-EXITING-RESTARTER pred id displayer receiver) ;procedure -> values These create exiting restarters with the predicates, identifiers, and displayers given. MAKE-EXITING-RESTARTER makes a exiting restarter with the given continuation and returns it; WITH-EXITING-RESTARTER captures a continuation with which to create the restarter, and it calls RECEIVER, for whose dynamic extent the restarter is added to the front of the bound restarter list. WITH-EXITING-RESTARTER returns whatever values THUNK returns or zero values if the restarter is invoked. Value replacement restarters are intended to be used to return a replacement value when the original one was deemed unsuitable; e.g., they might be used to replace arguments of the wrong type. They answer true to RESTARTER? & RESTART/USE-VALUE?, and they are interactive in a parameterized manner. The identification of a value replacement restarter, in the sense of IDENTIFICATION, is usually just the symbol USE-VALUE. (MAKE-VALUE-REPLACEMENT-RESTARTER ;procedure throw displayer value-reader) -> restarter (WITH-VALUE-REPLACEMENT-RESTARTER ;procedure displayer value-reader receiver) -> values These create value replacement restarters with the given displayers and value readers. MAKE-VALUE-REPLACEMENT-RESTARTER creates a restarter with the given continuation and returns it, while WITH-VALUE-REPLACEMENT-RESTARTER captures a continuation, creates a restarter with that continuation, & calls RECEIVER, for whose dynamic extent the restarter is added to the front of the bound restarter list, with an argument of the restarter. If invoked interactively, the restarter calls VALUE-READER with zero arguments and sends the value that VALUE-READER returns to the restarter's continuation. **** Standard restarter types The condition system provides five built-in types of restarters for very common idioms. They are each specified as the generic predicate to which all instances answer true. FIND-RESTARTER can be used in conjunction with such a predicate to find the first instance of a bound restarter that answers true to a given predicate, i.e. the first restarter of a particular type; SELECT-RESTARTERS can be used to obtain a list of them. (RESTART/ABORT? obj) -> boolean ;predicate Aborting is completely terminating the computation and exiting out elsewhere. The computation is neither continued nor retried in any way. The most common use for aborting restarters is to abort back to the REPL or to exit the REPL entirely. ABORT restarters accept zero arguments. (RESTART/IGNORE? obj) -> boolean ;predicate Certain conditions, usually only non-serious ones, may sometimes be simply ignored as if there were no problem. For instance, note conditions usually have associated IGNORE restarters so that execution can easily proceed after possibly displaying the note somehow. IGNORABLE-ERROR signals that a semantic inconsistency occurred, but one for which there is a single, simple recovery path, so the condition can be ignored. IGNORE restarters accept zero arguments. (RESTART/RETRY? obj) -> boolean ;predicate These restarters are for retrying computations from the beginning after changing some external state that is expected to allow the computation to succeed after another attempt. For instance, an error that denotes a file's absence may be restarted after creating a file. RETRY restarters accept zero arguments. (RESTART/USE-VALUE? obj) -> boolean ;predicate These restarters allow one to retry a computation with a different input value from the original; for example, a procedure might test one of its arguments, and, if it does not satisfy some predicate, signal a 'wrong type argument error' after establishing a USE-VALUE restarter that would allow a handler to supply a different argument. USE-VALUE restarters accept one argument. (RESTART/STORE-VALUE? obj) -> boolean ;predicate STORE-VALUE restarters are like USE-VALUE restarters; however, not only do they continue with a new input value, but they also store the input value so that the old one will not be used again. A common example of this is for unbound variable references: a USE-VALUE restarter might be invoked, but then any other references to the variable would cause similar unbound variable errors; on the other hand, a STORE-VALUE restarter would use a value and also bind or assign the variable to the new value. STORE-VALUE restarters accept one argument.