Доброе утро, Бойко!

> Библиотекой назвать вряд ли стоит, там всего несколько макро- и шаблонных 
> определений.  Выложил здесь:
> http://www.math.bas.bg/bantchev/misc/m.cpp
> В следующем тексте написано немного об идеологии:
> http://www.math.bas.bg/bantchev/misc/neater.pdf , но он немного различается 
> как раз в отношении макроопределений для циклов.  Впрочем, в этом разберетесь 
> легко.

Посмотрел. Понравились макросы для отладочной печати. Буду пользоваться. На 
счёт циклов — в коммерческом ПО вряд ли, в своих проектах — возможно.

Понравилась реализация необязательного параметра n в макросе fora:

#define fora(a,i,n,...) {__VA_ARGS__; int _ = #n[0]=='\0' ? asize(a) : n+0; \
                         for(int i=0; i<_; ++i) {     // entire array processing

Когда его нет, #n раскрывается в пустую строчку, а n+0 в +0, что является 
корректным выражением. Не удивлюсь, если современные компиляторы истинность 
строки #n[0]=='\0' определят во время трансляции и во время выполнения 
ветвления уже не будет.

Мой пример выглядел бы так:

int row, col;  // используются после цикла, нельзя объявлять внутри.
loop (
  row = 0; col = 0
, row < MAXROW && elem_at(row, col) == 0
, ++col;
  if (col == MAXCOL) {
    col = 0;
    ++row;
  }
)
  // тело пустое, как я и предполагал
fin();
Цикл с пустым телом.

Фишка этого примера в том, что он записывается целиком в рамках структурного 
программирования: без goto, break и return. И, кроме того, пример демонстрирует 
идиому структурного программирования для поиска элемента в последовательности:

<установить на начало>
while (! <достигли конца> && ! <элемент обнаружен>)
  <вычисление следующего и переход к нему>
if (<достигли конца>)
  <действия, если элемент не найден>
else
  <действия, если элемент найден>

Просто поразительно, как часто такой подход позволяет распутывать сложные 
циклы. Сам порой удивляюсь, что через эту идиому красиво описываются иные 
сложные задачи. Главное сформулировать задачу как задачу поиска. Сравнить две 
строки на равенство — _найти_ первый неравный символ, например.

А пример — поиск в двумерной таблице — потому и выбран, что большинство 
программистов не представляют, как его решить без двух вложенных циклов и 
нелокального перехода. Даже в учебниках его демонстрируют как пример, когда 
«goto необходимо».

> то, мне кажется, его легко переписать и стандартными for:
>
> for (row=0; row < MAXROW; ++row)
>   for (col=0; col < MAXCOL; ++col)
>     if (elem_at(row,col)) goto x;
> x:
>
> По-моему, так текст и короче, и разобрать легче, а и выполняемых на каждом 
> шагу действий меньше.  Если goto очень раздражает (не меня), то можно и без 
> него:
>
> for (row=0; row < MAXROW; ++row) {
>   for (col=0; col < MAXCOL; ++col)
>     if (elem_at(row,col)) break;
>   if (col < MAXCOL) break;
> }
Я знаю, в случаях со вложенными циклами в данном примере выполняется на одну 
проверку меньше. Плата за структурное программирование. В варианте Сергея 
Абрамова (в следующем письме) вводится дополнительная булевская переменная и 
тоже требуется дополнительная проверка. 

-----Original Message-----
From: Boyko Bantchev [mailto:boyk...@gmail.com] 
Sent: Tuesday, August 8, 2017 11:31 PM
To: refal@botik.ru
Subject: Re: FW: Рефал умер?

Здравствуйте, Александр!

> С интересом бы посмотрел на такую библиотеку макросов. Попробовал бы 
> переписать с её использованием два примера циклов while из предыдущего 
> письма. У вас она где-нибудь в интернете опубликована?

Библиотекой назвать вряд ли стоит, там всего несколько макро- и шаблонных 
определений.  Выложил здесь:
http://www.math.bas.bg/bantchev/misc/m.cpp

Чудес не ожидайте, вещи совсем простые.
С другой стороны, там не только о циклах, но и пара других, как мне кажется, 
полезных вещей.  Буду рад, если что-то вам пригодится.

В следующем тексте написано немного об идеологии:
http://www.math.bas.bg/bantchev/misc/neater.pdf , но он немного различается как 
раз в отношении макроопределений для циклов.  Впрочем, в этом разберетесь легко.

Что касается вашего первого примера с while

int row = 0, col = 0;
while (row < MAXROW && elem_at(row, col) == 0) {
  ++col;
  if (col == MAXCOL) {
    col = 0;
    ++row;
  }
}

то, мне кажется, его легко переписать и стандартными for:

for (row=0; row < MAXROW; ++row)
  for (col=0; col < MAXCOL; ++col)
    if (elem_at(row,col)) goto x;
x:

По-моему, так текст и короче, и разобрать легче, а и выполняемых на каждом шагу 
действий меньше.  Если goto очень раздражает (не меня), то можно и без него:

for (row=0; row < MAXROW; ++row) {
  for (col=0; col < MAXCOL; ++col)
    if (elem_at(row,col)) break;
  if (col < MAXCOL) break;
}

Ответить