---As for the Lisp version, Common Lisp doesn't have standard finalizers, though many implementations provide them in one form or another. Most Lispers prefer to use with-whatever type constructs to assure "death conditions".
// ch04_ex13.javaclass ch04_ex13_Tank {
static int num_tanks = 0;
int i;
boolean filled;ch04_ex13_Tank() {
i = num_tanks++;
filled = false;
}public void finalize() {
if (filled) {
System.out.println( "Error: tank " + i + " not empty at finalize!" );
}
}static void testTanks() {
// case 1: tank created, filled, emptied, thrown away
{
ch04_ex13_Tank tank = new ch04_ex13_Tank();
tank.filled = true;
tank.filled = false;
}// case 2: tank created, filled, thrown away
{
ch04_ex13_Tank tank = new ch04_ex13_Tank();
tank.filled = true;
}// case 3: tank created & thrown away
{
new ch04_ex13_Tank();
}
}public static void main(String[] args) {
testTanks();
System.gc();
}
}
---
14:03 -- starting 4.13, Lisp version
14:41 -- done
---
;;;; chapter 4, ex 13
(defclass ch04-ex13-tank ()
((num-tanks :initform 0 :accessor tank-num-tanks :allocation :class)
(i :accessor tank-i)
(filled :initarg :filled :initform nil :accessor tank-filled)))
(defmethod finalize-tank ((tank ch04-ex13-tank))
(if (tank-filled tank)
(format t "Error: tank ~d not empty at finalize!" (tank-num-tanks tank))))
(defmethod initialize-instance :after ((tank ch04-ex13-tank)
&rest initargs)
(declare (ignore initargs))
(setf (tank-i tank) (tank-num-tanks tank))
(incf (tank-num-tanks tank)))
(defmacro with-ch04-ex13-tank ((tank tank-init) &body body)
`(let ((,tank ,tank-init))
(unwind-protect
(progn ,@body)
(finalize-tank ,tank))))
(defun test-tanks ()
;; case 1: Tank created, filled, emptied, thrown away
(with-ch04-ex13-tank (tank (make-instance 'ch04-ex13-tank))
(setf (tank-filled tank) t)
(setf (tank-filled tank) nil))
;; case 2: Tank created, filled, thrown away
(with-ch04-ex13-tank (tank (make-instance 'ch04-ex13-tank))
(setf (tank-filled tank) t))
;; case 3: Tank created & thrown away
(with-ch04-ex13-tank (tank (make-instance 'ch04-ex13-tank))))
---
(test-tanks) prints "Error: tank 1 not empty at finalize!" As various people have pointed out on comp.lang.lisp and elsewhere, one should only rarely use garbage collection (and hence finalization) for any resource but memory, and possibly to catch bugs.