8
$\begingroup$

According to Wikipedia:

The cleanup behavior now generally called "finally" was introduced in NIL (New Implementation of LISP) in the mid- to late-1970s as UNWIND-PROTECT. This was then adopted by Common Lisp.

When did other languages begin to adopt this functionality (and rename it finally)?

I have not yet found any languages developed in the 80s supporting this functionality. Ada 83 has exception handling but no finally. Contemporaneous versions of Pascal didn't have exception handling. Modula-2 and Oberon didn't either (although this was added much later). C++ added exception handling in 1990 but they (purposefully) did/do not support finally.

I haven't been able to figure out when Objective-C, Perl, or Erlang added exception handling support.

Anyhow, skipping ahead to 1996, Borland Delphi, Java, and Python all have finally and Ruby has ensure. What exactly am I missing between the late 70's and the mid-90's?

$\endgroup$
3
  • $\begingroup$ Strictly speaking, Delphi introduced try-finally-end and try-except-end which are distinct. The first case is used heavily for e.g. destruction of manually-created objects, but doesn't come with the full overhead of exceptions. $\endgroup$ Nov 10, 2023 at 6:57
  • 1
    $\begingroup$ UNWIND-PROTECT was also in MacLisp, I thought NIL and Common Lisp inherited it from there. $\endgroup$
    – Barmar
    Nov 10, 2023 at 17:46
  • $\begingroup$ UNWIND-PROTECT was addd to Maclisp in Sep 1978. Though it could be that it was coming from Lisp Machine Lisp and/or NIL. $\endgroup$ Nov 13, 2023 at 21:23

2 Answers 2

6
$\begingroup$

This probably isn't a complete answer, but Microsoft introduced a nonstandard __finally mechanism in their Structured Exception Handling feature. It's a feature of Visual C++ and some aspects are backed by Win32 API functions.

From Microsoft-specific exception handling mechanisms:

It features the finally mechanism not present in standard C++ exceptions (but present in most imperative languages introduced later).

The references quoted on that page don't support an early introduction date (Matt Pietrek wrote about SEH in 1997), but my recollection was that this feature was present in Visual C++ in the early 1990s. I am fairly certain its introduction preceded the finally keyword in Java.

$\endgroup$
3
  • $\begingroup$ I'll wait to see what other answers I get, but there does seem to be evidence this is from 1995 at the latest ( google.com/books/edition/Microsoft_Visual_C++/… ) $\endgroup$ Nov 10, 2023 at 0:56
  • $\begingroup$ And here suggests 1993 at the latest: groups.google.com/g/comp.os.ms-windows.programmer.tools/c/… $\endgroup$ Nov 10, 2023 at 1:07
  • 1
    $\begingroup$ That Wikipedia article needs some work. __finally is a feature of MSVC (as you said), not of SEH as such. It's available in C as well as C++, and they may have added it just for C, where it's actually needed (in the presence of SEH) since you can't accomplish the same thing with destructors. $\endgroup$
    – benrg
    Nov 10, 2023 at 8:01
5
$\begingroup$

MDL in 1977

The MDL Primer and Manual (PDF) from 1977 documents UNWIND. MDL is a slightly unusual variant of Lisp.

Page 150, 16.6 UNWIND

UNWIND is an FSUBR that takes two arguments, usually FORMs. It EVALs the first one, and, if the EVAL returns normally, the value of the EVAL call is the value of UNWIND. If, however, during the EVAL a non-local return attempts to return below the UNWIND FRAME in the control stack, the second argument is EVALed, its value is ignored, and the non-local return is completed. The second argument is evaluated in the environment that was present when the call to UNWIND was made. This facility is useful for cleaning up data bases that are in inconsistent states and for closing temporary CHANNEls that may be left around. FLOAD sets up an UNWIND to close its CHANNEL if the user attempts to ERRET without finishing the FLOAD. Example:

<DEFINE CLEAN ACT ("AUX" (C <OPEN "READ" "A FILE">))
  #DECL ((C) <OR CHANNEL FALSE> ...)
  <COND (.C
         <UNWIND <PROG () ... <CLOSE .C>>
                 <CLOSE .C>>)>>

Above defines a function with a local parameter C, which is the result of opening a file to read. It's either a channel or FALSE. If C is a channel then, protected, by an UNWIND, then some operations in the PROG expressions are executed. If there is a non-local transfer out of this UNWIND, the second form, a CLOSE operation is executed.

In Common Lisp this would be roughly:

(defun clean (&aux (c (open "a file" :direction :input)))
  (declare (type (or channel null) c))
  (when c
    (unwind-protect (progn ... )
      (close c))))

Maclisp in 1978

Maclisp documents UNWIND-PROTECT in Sept. 1978: http://ml.cddddr.org/lispnews/lispnews-19780916.html

(UNWIND-PROTECT <e> u1 u2 ... u<n>)

  The form <e> will be evaluated, but if the stack is "unwound" past
  the point of the UNWIND-PROTECT for ANY REASON,
  then the unwinder must cause the evaluation, in order,
  of u1 through u<n> in the environment that obtains by first 
  unwinding to the stack point of the UNWIND-PROTECT; then the 
  unwinding may continue.  If <e> terminates normally, then
  the value will be that obtained from <e>, but the forms u1 
  through u<n> will be evaluated also.  The intent is
  that the operation of <e> will do some things that need to be
  undone after sucessful completion, but which can not be undone 
  merely by lambda-binding (eg, closing an opened file).  Thus any 
  aborting of the evaluation of <e> will not leave undesired states 
  hanging around.  Before the u<n>'s are run, NOINTERRUPT is set to
  T, so that asynchronous conditions cannot cause premature termination
  of the handlers.  It is restored to its previous value upon
  completion of the u<n>'s.  If a THROW is done, the user must reset
  NOINTERRUPT to the value he wishes it to be!  The UNWIND-PROTECT
  frame is removed from the stack BEFORE the u<n>'s are run so that
  they may freely do THROWS (et al.).

It was also in NIL (New Implementation of Lisp) and Lisp Machine Lisp. In the early 80s it was also defined by Common Lisp (Common Lisp the Language, 1984, p 140-142).

$\endgroup$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .