Next: Handler stack unwinding caveat, Previous: Creating new exception classes, Up: Exception handling
More often useful than even
guarantees that some code is executed when the stack unwinds, whether
because of normal execution or because of a signalled exception.
Here is an example of use of
#ensure: and a situation where the
stack can unwind even without a signal:
Object subclass: ExecuteWithBreak [ | breakBlock | break: anObject [ breakBlock value: anObject ] valueWithBreak: aBlock [ "Sets up breakBlock before entering the block, and passes self to the block." | oldBreakBlock | oldBreakBlock := breakBlock. ^[breakBlock := [:arg | ^arg]. aBlock value] ensure: [breakBlock := oldBreakBlock] ] ]
This class provides a way to stop the execution of a block without
exiting the whole method as using
^ inside a block would do.
The use of
#ensure: guarantees (hence the name "ensure") that even
breakBlock is invoked or an error is handled by unwinding,
the old “break block” will be restored.
The definition of
breakBlock is extremely simply; it is an
example of the general unwinding feature of blocks, that you have
probably already used:
(history includesKey: num) ifTrue: [ ^self error: 'Duplicate check number' ].
You have probably been using
#ensure: without knowing. For example,
File>>#withReadStreamDo: uses it to ensure that the file is
closed when leaving the block.