Разбирал очередной LOOP, увидел вот что. Не только выход из LOOP с помощью RETURN, но и выход из FOR c помощью EXIT.
Код:
   d := 0; i := 0;
   LOOP
      IF d = LEN (array, 1) THEN
         RETURN FALSE
      END;
      FOR i := 0 TO LEN (array, 0) - 1 DO
         PrepareForCheck1 (array [d, i]);
         IF Check1 (array [d, i]) THEN
            EXIT
         END;
         PrepareForCheck2 (array [d, i]);
         IF Check2 (array [d, i]) THEN
            EXIT
         END;
      END; (* for i *)
      INC (d);
   END; (* loop *)
   HandleSuccess ();
   RETURN TRUE
Первым делом объединил процедуры PrepareForCheckN с CheckN, чтобы можно было целиком поставить в IF (побочных эффектов у них не было).
Код:
   d := 0; i := 0;
   LOOP
      IF d = LEN (array, 1) THEN
         RETURN FALSE
      END;
      FOR i := 0 TO LEN (array, 0) - 1 DO
         IF PrepareAndCheck1 (array [d, i]) THEN
            EXIT
         END;
         IF PrepareAndCheck2 (array [d, i]) THEN
            EXIT
         END;
      END; (* for i *)
      INC (d);
   END; (* loop *)
   HandleSuccess ();
   RETURN TRUE
Уже видно, что внутри FOR условия можно объединить с помощью OR, а сам FOR при этом легко превращается в обычный поисковый WHILE. По сути EXIT из FOR - это успешное завершение поиска, которое надо сигнализировать за пределы LOOP. Заводим для этого переменную res: BOOLEAN:
Код:
   res := FALSE; d := 0;
   WHILE (d < LEN (array, 1)) & ~res DO
      i := 0;
      WHILE (i < LEN (array, 0)) & ~res DO
         res := PrepareAndCheck1 (array [d, i]) OR PrepareAndCheck2 (array [d, i]);
         INC (i);
      END; (* while i *)
      INC (d);
   END; (* while d *)
   IF res THEN
      HandleSuccess ();
   END;
   RETURN res
Значения i и d не используются в HandleSuccess. Если бы использовались, то надо было бы их уменьшить на 1 при успешном завершении поиска.
Итого, устранены три преждевременных выхода из циклов, добавлена одна локальная переменная, исходник уложился в понятный шаблон и стал короче на 6 строк (правда, пришлось написать вспомогательную процедуру, но она пригодилась ещё раз для усмирения аналогичного LOOP'а в том же модуле).
Кстати, сравните приведённый выше код вот с этим:
Код:
   res := FALSE; d := 0;
   WHILE (d < LEN (array, 1)) & ~res DO
      i := 0;
      WHILE (i < LEN (array, 0)) & ~(PrepareAndCheck1 (array [d, i]) OR PrepareAndCheck2 (array [d, i])) DO
         INC (i);
      END; (* while i *)
      res := ~(i < LEN (array, 0));
      INC (d);
   END; (* while d *)
   IF res THEN
      HandleSuccess ();
   END;
   RETURN res
В последнем варианте присвоение res вынесено за цикл, а искомое условие записано в условии цикла. Хотя этот вариант более каноничен, мне всё же препоследний кажется более читабельным из-за явного присвоения res и явного визуального сходства двух WHILE.