GNU Smalltalk - выход из цикла whileTrue без возврата - PullRequest
0 голосов
/ 07 октября 2018

Каков простой и лаконичный способ отрыва от цикла whileTrue в GNU Smalltalk, который не требует возврата?

Вот мой код.Я хочу выйти из цикла в строке 31 в конце, если char_stack пусто.

https://gist.github.com/SYZYGY-DEV333/ea3f5eeb3473927c8faa294bb72a8858

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Одна из статей журнала 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].

0 голосов
/ 07 октября 2018

В общем, Smalltalk не имеет способа выхода из цикла, за исключением возврата из включающего метода.

Попробуйте извлечь ваш цикл в другой метод, из которого вы можете вернуться, чтобы выйти из цикла.

В некотором смысле, язык Smalltalk даже не имеет циклов ... но некоторые методы могут вычислять блоки более одного раза.Следовательно, у него нет специального способа завершения «петель».Возврат - это путь.

Если вы еще этого не сделали, ознакомьтесь с различными итерационными методами Collection: do:, select:, collect:, detect:ifNone:, ... Последнийэто еще один способ запустить «неполный» цикл над коллекцией, но он не решает все случаи, в которых вы можете захотеть сделать «разрыв».

...