<!-- <a style="font-size: 120%" href="https://www.udemy.com/course/common-lisp-programming/?couponCode=LISPY-XMAS2023" title="This course is under a paywall on the Udemy platform. Several videos are freely available so you can judge before diving in. vindarel is (I am) the main contributor to this Cookbook."> Discover our contributor's Lisp course with this Christmas coupon.</a> -->
📢 New videos: <ahref="https://www.youtube.com/watch?v=h_noB1sI_e8">web dev demo part 1</a>, <ahref="https://www.youtube.com/watch?v=xnwc7irnc8k">dynamic page with HTMX</a>, <ahref="https://www.youtube.com/watch?v=Zpn86AQRVN8">Weblocks demo</a>
<p>Let’s dive into it step by step. More resources are given afterwards.</p>
<h2id="ignoring-all-errors-returning-nil">Ignoring all errors, returning nil</h2>
<p>Sometimes you know that a function can fail and you just want to
ignore it: use <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/m_ignore.htm">ignore-errors</a>:</p>
<pre><codeclass="language-lisp">(ignore-errors
(/ 3 0))
; in: IGNORE-ERRORS (/ 3 0)
; (/ 3 0)
;
; caught STYLE-WARNING:
; Lisp error during constant folding:
; arithmetic error DIVISION-BY-ZERO signalled
; Operation was (/ 3 0).
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
NIL
#<DIVISION-BY-ZERO {1008FF5F13}>
</code></pre>
<p>We get a welcome <code>division-by-zero</code> warning but the code runs well and
it returns two things: <code>nil</code> and the condition that was signaled. We
could not choose what to return.</p>
<p>Remember that we can <code>inspect</code> the condition with a right click in Slime.</p>
<h2id="catching-any-condition-handler-case">Catching any condition (handler-case)</h2>
<!-- we will say "handling" for handler-bind -->
<p><code>ignore-errors</code> is built from <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/m_hand_1.htm">handler-case</a>. We can write the previous
example by catching the general <code>error</code> but now we can return whatever
;; Caught division by zero: arithmetic error DIVISION-BY-ZERO signalled
;; Operation was (/ 3 0).
;; NIL
</code></pre>
<p>This workflow is similar to a try/catch as found in other languages, but we can do more.</p>
<h2id="handler-case-vs-handler-bind">handler-case VS handler-bind</h2>
<p><code>handler-case</code> is similar to the <code>try/catch</code> forms that we find in
other languages.</p>
<p><ahref="http://www.lispworks.com/documentation/HyperSpec/Body/m_handle.htm">handler-bind</a> (see the next examples), is what to use
when we need absolute control over what happens when a signal is
raised. It allows us to use the debugger and restarts, either
interactively or programmatically.</p>
<p>If some library doesn’t catch all conditions and lets some bubble out
to us, we can see the restarts (established by <code>restart-case</code>)
anywhere deep in the stack, including restarts established by other
libraries that this library called. And <em>we can see the stack
trace</em>, with every frame that was called and, in some lisps, even see
local variables and such. Once we <code>handler-case</code>, we “forget” about
this, everything is unwound. <code>handler-bind</code> does <em>not</em> rewind the
stack.</p>
<p>Before we properly see <code>handler-bind</code>, let’s study conditions and restarts.</p>
<h2id="defining-and-making-conditions">Defining and making conditions</h2>
<p>We define conditions with <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/m_defi_5.htm">define-condition</a> and we make (initialize) them with <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/f_mk_cnd.htm">make-condition</a>.</p>
<p>We can use <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/e_error.htm#error">error</a> in two ways:</p>
<ul>
<li><code>(error "some text")</code>: signals a condition of type <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/e_smp_er.htm">simple-error</a>, and opens-up the interactive debugger.</li>
<li><code>(error 'my-error :message "We did this and that and it didn't work.")</code>: creates and throws a custom condition with its slot “message” and opens-up the interactive debugger.</li>
<p>Throwing these conditions will enter the interactive debugger, where
the user may select a restart.</p>
<p><code>warn</code> will not enter the debugger (create warning conditions by subclassing <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/e_smp_wa.htm">simple-warning</a>).</p>
<p>Use <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/f_signal.htm">signal</a> if you do not want to enter the debugger, but you still want to signal to the upper levels that something <em>exceptional</em> happened.</p>
<p>And that can be anything. For example, it can be used to track
progress during an operation. You would create a condition with a
<code>percent</code> slot, signal one when progress is made, and the
higher level code would handle it and display it to the user. See the
<p>We have a piece of code that we know can throw conditions. Here,
<code>divide-with-restarts</code> can signal an error about a division by
zero. What we want to do, is our higher-level code to automatically
handle it and call the appropriate restart.</p>
<p>We can do this with <code>handler-bind</code> and <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/f_invo_1.htm#invoke-restart">invoke-restart</a>:</p>
<h2id="running-some-code-condition-or-not-finally-unwind-protect">Running some code, condition or not (“finally”) (unwind-protect)</h2>
<p>The “finally” part of others <code>try/catch/finally</code> forms is done with <ahref="http://www.lispworks.com/documentation/HyperSpec/Body/s_unwind.htm">unwind-protect</a>.</p>
<p>It is the construct used in “with-“ macros, like <code>with-open-file</code>,
<p>We <em>do</em> get the interactive debugger (we didn’t use handler-bind or
anything), but our message is printed afterwards anyway.</p>
<h2id="conclusion">Conclusion</h2>
<p>You’re now more than ready to write some code and to dive into other resources!</p>
<h2id="resources">Resources</h2>
<ul>
<li><ahref="http://gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html">Practical Common Lisp: “Beyond Exception Handling: Conditions and Restarts”</a> - the go-to tutorial, more explanations and primitives.</li>
<li>Common Lisp Recipes, chap. 12, by E. Weitz</li>
<li><ahref="http://nklein.com/2011/03/tutorial-introduction-to-conditions-and-restarts/">Video tutorial: introduction on conditions and restarts</a>, by Patrick Stein.</li>
<li><ahref="http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html">Condition Handling in the Lisp family of languages</a></li>
<li><ahref="https://z0ltan.wordpress.com/2016/08/06/conditions-and-restarts-in-common-lisp/">z0ltan.wordpress.com</a> (the article this recipe is heavily based upon)</li>
</ul>
<h2id="see-also">See also</h2>
<ul>
<li><ahref="http://jacek.zlydach.pl/blog/2019-07-24-algebraic-effects-you-can-touch-this.html">Algebraic effects - You can touch this !</a> - how to use conditions and restarts to implement progress reporting and aborting of a long-running calculation, possibly in an interactive or GUI context.</li>
<li><ahref="https://github.com/stylewarning/lisp-random/blob/master/talks/4may19/root.lisp">A tutorial on conditions and restarts</a>, based around computing the roots of a real function. It was presented by the author at a Bay Area Julia meetup on may 2019 (<ahref="https://github.com/stylewarning/talks/blob/master/4may19-julia-meetup/Bay%20Area%20Julia%20Users%20Meetup%20-%204%20May%202019.pdf">talk slides here</a>).</li>
<li><ahref="https://lisper.in/restarts#signaling-validation-errors">lisper.in</a> - example with parsing a csv file and using restarts with success, <ahref="https://www.reddit.com/r/lisp/comments/7k85sf/a_tutorial_on_conditions_and_restarts/drceozm/">in a flight travel company</a>.</li>
<li><ahref="https://github.com/svetlyak40wt/python-cl-conditions">https://github.com/svetlyak40wt/python-cl-conditions</a> - implementation of the CL conditions system in Python.</li>
📹 Discover <astyle="color: darkgrey; text-decoration: underline",href="https://www.udemy.com/course/common-lisp-programming/?referralCode=2F3D698BBC4326F94358">our contributor's Common Lisp video course on Udemy</a>