The less-familiar parts of Lisp for beginners — unwind-protect

While this is not really in the realm of uncommon commands, being a fairly useful and frequently-used feature, I want to point it out for the C++ programmers who are new to Lisp, just to reinforce its usefulness.

In both C++ and Lisp, a function or block can exit in some non-trivial ways.  Flow could jump out of the block with a goto, or a called function could throw an exception that is only caught somewhere higher up.  Lisp has equivalents to those.  There is no setjmp()/longjmp() in Lisp, but the C++ programmer should consider himself or herself forbidden from using those, they do bad things.

There will be times when the program does something, and needs to have a guaranteed method of undoing it no matter how execution passes out of the block.  In C++, this is commonly done by putting the shutdown behaviour in an object destructor and instantiating the object on the stack as an auto variable.  So, where in C one writes fopen() and fclose() on a file, in C++ one commonly uses iostream objects whose destructors close the file descriptor associated with the open file.  In this way, the programmer can avoid leaking file descriptors when an exception exits the function after the file has opened, but before it has closed.

An alternative in C++ is to enclose everything in a try{} block, and do the cleanups in the corresponding catch, then re-throw the exception.  This is a bit klunky, though, and does require that the closing code is written twice, once in the regular flow, and once in the exception caught case.

In Lisp, there are no object destructors, so that mechanism isn’t available.  Instead, in Lisp the programmer typically uses unwind-protect.  This special operator is a bit different from the C++ try/catch sequence, because the unwind form is executed in all cases, not just in the exception case.  It essentially says that, however you exit the protected form, immediately execute the cleanup form before proceeding further.  If you want to think of it a C++ try/catch with an implicit catch of any exception followed by a re-throw, you can, but note that important distinction, the cleanup form is executed even in the normal flow, then the block exits normally.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

反垃圾邮件 / Anti-spam question * Time limit is exhausted. Please reload CAPTCHA.