Одна из статей журнала Byte (1982) под названием Построение структур управления в системе Smalltalk-80 от Питер Дойч показывает, как легко реализовать разрывы во время цикладля нечастых событий , которые могут происходить внутри цикла.
Для реализации этого нам нужен только новый класс и расширение до BlockClosure
, что составляет всего 9 строк кода (!).
Класс : BlockWithExit
, подкласс Object
с двумя иварами exit
и block
и следующими методами
on: aBlock
block := aBlock
value
exit := [^nil].
^block value
exit
exit value
Расширение
BlockClosure>>withExit
^BlockWithExit new on: self
и все!
Пример
Найти максимум коллекции доего исчерпание или пока nil
не будет найдено ( нечастое событие )
maxBeforeNil: aCollection
| max supplier loop |
max := 0.
supplier := aCollection readStream.
loop := [
[supplier atEnd]
whileFalse: [
value := supplier next.
value isNil ifTrue: [loop exit].
max := max max: value]] withExit.
loop value.
^max
Почему это работает так, как работает? Поскольку блокс нелокальным возвратом выходит из метода, который определяет блок .
В этом случае этот метод равен BlockWithExit>>value
, поэтому, когда [^nil]
равноНачиная с loop exit
, поток выходит из value
и отправляется отправителю сразу после loop value
.
Выдающимся следствием открытия Дойча является то, что весь механизм Exceptions
может быть построен с использованием этого самого трюка определения выходного блока в иваре, например: exit := [^nil]
.