User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cl:macros:with-simple-restart [2019/07/14 17:00]
cl:macros:with-simple-restart [2019/10/19 17:00] (current)
Line 1: Line 1:
 +====== Macro WITH-SIMPLE-RESTART ======
 +
 +====Syntax====
 +  * **with-simple-restart** //(name format-control format-argument''​*''​ form''​*''​)//​ → //​result''​*''//​
 +
 +====Arguments and Values====
 +  * //name// - a //​[[CL:​Glossary:​symbol]]//​.
 +  * //​format-control//​ - a //​[[CL:​Glossary:​format control]]//​.
 +  * //​format-argument//​ - an //​[[CL:​Glossary:​object]]//​ (i.e. a //​[[CL:​Glossary:​format argument]]//​).
 +  * //forms// - an //​[[CL:​Glossary:​implicit progn]]//.
 +  * //results// - in the normal situation, the //​[[CL:​Glossary:​values]]//​ returned by the //forms//; in the exceptional situation where the //​[[CL:​Glossary:​restart]]//​ named //name// is invoked, two values - **[[CL:​Constant Variables:​nil]]** and **[[CL:​Constant Variables:​t]]**.
 +
 +====Description====
 +**with-simple-restart** establishes a restart.
 +
 +If the restart designated by //name// is not invoked while executing //forms//, all values returned by the last of //forms// are returned. If the restart designated by //name// is invoked, control is transferred to **with-simple-restart**,​ which returns two values, **[[CL:​Constant Variables:​nil]]** and **[[CL:​Constant Variables:​t]]**.
 +
 +If //name// is **[[CL:​Constant Variables:​nil]]**,​ an anonymous restart is established.
 +
 +The //​format-control//​ and //​format-arguments//​ are used report the //​[[CL:​Glossary:​restart]]//​.
 +
 +====Examples====
 +<​blockquote>​
 +([[CL:​Macros:​defun]] read-eval-print-loop (level)
 +  (with-simple-restart ([[CL:​Restarts:​abort]] "Exit command level ~D." level)
 +    ([[CL:​Macros:​loop]]
 +      (with-simple-restart ([[CL:​Restarts:​abort]] "​Return to command level ~D." level)
 +        ([[CL:​Special Operators:​let]] ((form ([[CL:​Functions:​prog2]] (fresh-line) ([[CL:​Functions:​read]]) ([[CL:​Functions:​fresh-line]]))))
 +          ([[CL:​Functions:​prin1]] ([[CL:​Functions:​eval]] form))))))) <​r>​READ-EVAL-PRINT-LOOP</​r>​
 +
 +(read-eval-print-loop 1)
 +(+ 'a 3)
 +<​e>​Error:​ The argument, A, to the function + was of the wrong type.
 +The function expected a number.
 +To continue, type :CONTINUE followed by an option number:
 +1: Specify a value to use this time.
 +2: Return to command level 1.
 +3: Exit command level 1.
 +4: Return to Lisp Toplevel.</​e>​
 +
 +([[CL:​Macros:​defun]] compute-fixnum-power-of-2 (x)
 +  (with-simple-restart (nil "Give up on computing 2^~D." x)
 +    ([[CL:​Special Operators:​let]] ((result 1))
 +      ([[CL:​Macros:​dotimes]] (i x result)
 +        ([[CL:​Macros:​setf]] result ([[CL:​Functions:​math-multiply|*]] 2 result))
 +        ([[CL:​Macros:​unless]] ([[CL:​Functions:​fixnump]] result)
 +          ([[CL:​Function:​error]] "Power of 2 is too large."​)))))) <​r>​COMPUTE-FIXNUM-POWER-OF-2</​r>​
 +          ​
 +([[CL:​Macros:​defun]] compute-power-of-2 (x)
 +  ([[CL:​Macros:​or]] (compute-fixnum-power-of-2 x) '​something-big)) <​r>​COMPUTE-POWER-OF-2</​r>​
 +
 +(compute-power-of-2 10) <​r>​1024</​r>​
 +
 +(compute-power-of-2 10000)
 +<​e>​Error:​ Power of 2 is too large.
 +To continue, type :CONTINUE followed by an option number.
 +1: Give up on computing 2^10000.
 +2: Return to Lisp Toplevel
 +Debug> :continue 1</e>
 +<​r>​SOMETHING-BIG</​r>​
 +</​blockquote>​
 +
 +====Side Effects====
 +None.
 +
 +====Affected By====
 +None.
 +
 +====Exceptional Situations====
 +None.
 +
 +====See Also====
 +**[[CL:​Macros:​restart-case|Macro RESTART-CASE]]**
 +
 +====Notes====
 +**with-simple-restart** is shorthand for one of the most common uses of **[[CL:​Macros:​restart-case]]**.
 +
 +**with-simple-restart** could be defined by:
 +
 +<​blockquote>​
 +([[CL:​Macros:​defmacro]] with-simple-restart ​
 +    ((restart-name format-control &rest format-arguments)
 +     &​body forms)
 +  `([[CL:​Macros:​restart-case]] (progn ,@forms)
 +     ​(,​restart-name ()
 +         :​report ([[CL:​Symbols:​lambda]] (stream)
 +                   ​([[CL:​Functions:​format]] stream ,​format-control ,​@format-arguments))
 +       ​([[CL:​Functions:​values]] [[CL:​Constant Variables:​nil]] [[CL:​Constant Variables:​t]]))))
 +</​blockquote>​
 +
 +Because the second return value is **[[CL:​Constant Variables:​t]]** in the exceptional case, it is common (but not required) to arrange for the second return value in the normal case to be missing or **[[CL:​Constant Variables:​nil]]** so that the two situations can be distinguished.
 +
 +\issue{FORMAT-STRING-ARGUMENTS:​SPECIFY} \issue{FORMAT-STRING-ARGUMENTS:​SPECIFY}