Даю разгадку про Алгол-68 и Bash. В них не нужен цикл с постусловием, поскольку
в них внутри выражения можно писать оператор (кстати, эта идея заимствуется
многими современными языками программирования, например, Rust и Cotlin).
Bash, цикл с предусловием:
while
prog1
do
prog2
prog3
od
Bash, цикл с выходом посередине:
while
prog1
prog2
do
prog3
od
Bash, цикл с выходом посередине и пустым телом == цикл с постусловием:
while
prog1
prog2
prog3
do
:
od
Этот цикл будет продолжаться, пока программа prog3 будет выдавать нулевой,
успешный код возврата. И цепочка prog1; prog2; prog3 выполнится хотя бы один
раз. Цикл с постусловием. (Двоеточие в Bash — специальное обозначение пустой
команды, которая всегда выполняется успешно.)
> void sift(T a[], unsigned n, unsigned p) {
> unsigned j;
> T x = a[p];
> for (;;) {
> if (j=2*p+1, j+1<n && a[j]<a[j+1]) ++j;
> if (j>=n || a[j]<=x) break;
> a[p] = a[j]; p = j;
> }
> a[p] = x;
> }
Алгол-68 (не исключаю мелкие ошибки в синтаксисе):
proc sift = (ref [] T a, int n, int p) void: (
int j;
T x := a[p];
while (
if (j := 2*p + 1; j + 1 < n) and a[j] < a[j + 1] then j +:= 1;
j < n and a[j] > x
) do
a[p] := a[j]; p := j
od;
a[p] := x
)
Красота. И никаких break’ов и goto. Структурное программирование :-).
Книжка про Симулу следующая:
Андрианов А. Н., Бычков С. П., Хорошилов А. И. Программирование на языке
симула-67.— М.: Наука. Глав. ред. физ.-мат. лит., 1985.— 288 с.
Процитирую один фрагмент из книги, интересный в контексте рассылки
[email protected]:
Стр. 8:
«Авторы считают приятным долгом выразить благодарность … А. А. Веденову, С. А.
Романенко, А. Е. Фирсову за помощь в использовании рефал-систем на БЭСМ-6 и ЕС
ЭВМ …»
И ещё, стр. 169:
«При реализации широко применялся язык рефал [5], ориентированный на
программирование сложных символьных преобразований. Наличие на машинах БЭСМ-6 и
ЕС ЭВМ реализаций рефала [5, 14], практически полностью совместимых по входному
языку, позволило значительно сократить трудоёмкость разработки
симула-компиляторов, особенно компилятора для ЕС ЭВМ, основу которого составили
программы ранее разработанного транслятора с языка симула-67 для БЭСМ-6.»
Ссылки списка литературы (см. выше):
«5. Базисный РЕФАЛ. Описание языка и основные приемы программирования
(методические рекомендации). Вып. V-33.— М.: ЦНИПИАСС, 1974.— 95 с.
…
14. Климов Ан. В., Романенко С. А. Рефал в мониторной системе Дубна. Интерфейс
рефала и фортрана.— М., 1975.— 34 с. (Препринт/ИПМ им. М. В. Келдыша АН СССР)»
-----Original Message-----
From: Boyko Bantchev [mailto:[email protected]]
Sent: Thursday, August 10, 2017 12:45 AM
To: [email protected]
Subject: Re: FW: Рефал умер?
> был очень витиеватый цикл for, который мог быть даже while
Вот именно: while-ом можешь ты и быть, но for-ом все равно быть обязан.
Хочешь не хочешь, а for и «управляющая переменная» обязательны для цикла. Даже
когда переменная никак не нужна и нигде не используется.
Поэтому написал, что оператор цикла в Алголе-60 единственный.
А в Алголе-68 не так: там никакая часть не обязательна. Можно счетчик
использовать, можно и условие, но все на выбор.
(Еще более это развито в ПЛ/1 — в нем голова кружится от возможностей написать
цикл, как впрочем и почти все остальное. Цикл ПЛ/1 скопирован в REXX, который
и ныне здравствует.)
> Впрочем, и польза от разумной структурности тоже вполне обоснована
Конечно, это само собой, никто не спорит.
Проблема в том, что принято только пользу подчеркивать, а о вреде умалкивают.
Ниже приведу пример в этом духе.
> Читал как-то отечественную книжку 80-х годов про Симулу-67. Редкий
> метод в ней обходился без goto
Если и была такая книжка, не думаю что она показательна в данном отношении.
Книг по программированию на русском у меня много, а покупал их как раз в это
время. (Тогда у нас их продавали в большом количестве, очень недорого, и у
меня накопилась библиотека приличного
размера.) Но злоупотребление goto нигде не встречал.
> Под флагом и по причине борьбы за эффективность в программировании
> совершено больше преступлений, чем по всем остальным причинам вмести
> взятын. Включая непроходимую тупость.
> … в конце 70-х Владимир Леонидович Топунов учил что, если предполагаемый
> эффект от оптимизации меньше 10%, то не следует даже браться...
Роджер Хюи, автор (совместно с К.Айверсоном) и главный реализатор языка J
(наследника APL) утверждает, что никакую оптимизацию не стоит делать, если
приведет к улучшению не больше чем в два раза!
Но! Под оптимизацией можно понимать разные вещи. Меня в этой дискуссии
мотивирует не оптимизация в смысле повышения быстродействия, а экономия. Не
вводить лишнее, не повторять действия, расставить нужное где ему лучше быть.
Организовать программу из таких соображений, а не из соображений придерживания
к неясно чем полезным на практике правилам.
Приведу пример: процедура проталкивания в пирамиду. У меня она получается так:
void sift(T a[], unsigned n, unsigned p) {
unsigned j;
T x = a[p];
for (;;) {
if (j=2*p+1, j+1<n && a[j]<a[j+1]) ++j;
if (j>=n || a[j]<=x) break;
a[p] = a[j]; p = j;
}
a[p] = x;
}
Как во многих других случаях, цикл естественнее всего пишется с выходом из
середины тела.
А это вариант Н.Вирта из его известной книги — текст то ли на Модуле, то ли на
Обероне:
PROCEDURE sift(L, R: INTEGER);
VAR i, j: INTEGER; x: Item;
BEGIN i := L; j := 2*i+1; x := a[i];
IF (j < R) & (a[j] < a[j+1]) THEN j := j+1 END;
WHILE (j <= R) & (x < a[j]) DO
a[i] := a[j]; i := j; j := 2*j+1;
IF (j < R) & (a[j] < a[j+1]) THEN j := j+1 END
END;
a[i] := x
END sift;
Есть различия несущественные, но главная в моем понимании проблема здесь —
дублирование строк 4 и 7, только из желания избежать выхода из тела цикла, быть
«структурным». Не знаю чем это может быть полезным, для меня оно выглядит
нелепо. Хоть и из уст великих.
В самом первом варианте книги (на Паскале) Вирт использовал goto для выхода из
цикла и дублирования действий нет. Потом «эволюировал».