Страница 1 из 2

цикл FOR

СообщениеДобавлено: 13.10.2007 21:42:20
Alexander
Почему Вирт против использования значения переменной цикла
после выхода из цикла ? Из за того, что for может завершиться
не начавшись и переменная может быть не определена ?

И почему бы не использовать такие варианты ? :

Код: Выделить всё
X := 20;
for f := 10 to X do begin
  WriteLn(f);
  if f = 15 then break;
breakfor; // опциональный параметр
  WriteLn('Цикл был прерван. Значение F=', f);
endfor;  // опциональный параметр
  WriteLn('А сюда бы мы попали, если бы break не было. Значение F=', f);
end; {end for}
// сюда попадаем в любом случае, если Х < 10 то F = 10.
WriteLn('Значение F=', f);

СообщениеДобавлено: 13.10.2007 23:43:51
Deepthroat
А че так сложно?

Без дополнительных конструкций делаем так:
Код: Выделить всё
  X := 20;

  for f := 10 to X do
  begin
    WriteLn(f);

    if f = 15 then
    begin
      WriteLn('Цикл был прерван. Значение F = ', f);
      break;
    end;
  end;

  if f = X then
  begin
    WriteLn('А сюда бы мы попали, если бы break не было. Значение F = ', f);
  end;

  // сюда попадаем в любом случае, если Х < 10 то F = 10.
  WriteLn('Значение F = ', f);

Break - нехорошо, так что, когда надо, я использую while или изменяю значение X (лучше while, конечно). Ну это Вы и без меня знаете.

А насчет почему, то я думаю, что переменная цикла, по идее, вообще должна быть временной. А ее область видимости должна ограничиваться циклом, как это сделано в других языках.

СообщениеДобавлено: 13.10.2007 23:45:48
alexs
конструкция интересная - но логичнее распологать её после самого тела цикла:
Код: Выделить всё
X := 20;
for f := 10 to X do begin
  WriteLn(f);
  if f = 15 then break;
  WriteLn('А сюда бы мы попали, если бы break не было. Значение F=', f);
end
breakfor; // опциональный параметр
  WriteLn('Цикл был прерван. Значение F=', f);
endfor;  // опциональный параметр
{end for}

// сюда попадаем в любом случае, если Х < 10 то F = 10.
WriteLn('Значение F=', f);


хотя я не вижу смысла особого введения такой языковой конструкции (сам операторы break и continue) вобще не использую - уж очень они мне goto напоминают :-)

СообщениеДобавлено: 14.10.2007 01:10:36
debi12345
Зато был бы смысл в "CONTINUE/BREAK cycle_var" - чтобы явно указывать, для какого из вложенных циклов отрабатывать.

СообщениеДобавлено: 14.10.2007 14:07:32
Alexander
debi12345 писал(а):Зато был бы смысл в "CONTINUE/BREAK cycle_var" - чтобы явно указывать, для какого из вложенных циклов отрабатывать.


Да, это мысль !

СообщениеДобавлено: 14.10.2007 14:18:11
alexs
ну уж если совсем тюнинг наводить - то тогда так:
Код: Выделить всё
for i:=1 to 10 do
begin
  ...
breakfor
  ...
end


аналогично строить для циклов while-do и repeat-until

также можно отказаться от открывающего begin в циклах for и while - но это дело вкуса
лично мне они всёж нравятся (а может привычка).

СообщениеДобавлено: 14.10.2007 14:46:26
Tariel
в цикле for переменная вообще не используется , работа идет с регистром CX,
если использовать значение переменной после выхода,
надо в цикле постоянно присваивать значение переменной значения CX
проверка значения+оператор break по идее в цикле for на асме добавляет всего две команды,
begin вообще не должен добавлять ни одной команды,

Вообще, это тот случай когда С лучше паскаля.
на С
for (int i=10;i<20;i++){} //устанавливается значение цикла
на паскале
var i:integer; //создается переменная
for i:=10 to 20 do begin//устанавливается значение i + устанавливается значение цикла
end;

СообщениеДобавлено: 14.10.2007 14:56:18
bw
Мне не нравится идея использования break в циклах, это дурной тон. Так же как continue, exit/return и пр. Точка выхода из подпрограммы должна быть одна. Что касается переменной цикла, то считаю что область её видимости должна ограничиваться самим циклом. Но для этого придется определять её тип непосредственно в конструкции цикла (как мне кажется), для того что бы использование этой переменной трактовалось однозначно и что бы не сбить программиста с толку.
И еще, я бы отказался от текущего в паскале вида цикла в пользу изпользования директивы in как в Python и многих других языках:
Код: Выделить всё
for i in SomeIterator do WriteLn(i);
for i in range(10, 20) do WriteLn(i);
for row in SQLTableRows('users') do WriteLn('[row] ', String(row));

Может и не нужно определять тип переменной цикла, может он должен определяться автоматически :-), во время компиляции?

..bw

СообщениеДобавлено: 14.10.2007 15:05:03
alexs
bw писал(а):Может и не нужно определять тип переменной цикла, может он должен определяться автоматически

и встаёт вопрос смешения объявления переменных и кода - в паралельном треде на эту тему обсуждени.

bw писал(а):И еще, я бы отказался от текущего в паскале вида цикла в пользу изпользования директивы in как в Python и многих других языках:Код:

если не ошибаюсь - это в последних дельфях уже есть.

СообщениеДобавлено: 15.10.2007 08:17:33
Bonart
bw
bw писал(а):Мне не нравится идея использования break в циклах, это дурной тон. Так же как continue, exit/return и пр. Точка выхода из подпрограммы должна быть одна.

Подобный пуризм приводит к дополнительным многократным проверкам одних и тех же условий и к жуткому коду обработки ошибок.
Переходы "вперед и вверх" являются неотъемлемой частью структурного программирования и нет никакого смысла их ограничивать.
alexs писал(а):и встаёт вопрос смешения объявления переменных и код

А объявлять (т.е. руками приписывать тип) совсем не обязательно :)
bw писал(а):И еще, я бы отказался от текущего в паскале вида цикла в пользу изпользования директивы in как в Python и многих других языках

А смысл именно отказываться, а не дополнять? Цикл for .. in недоста
точно общий.
Alexander писал(а):Почему Вирт против использования значения переменной цикла

после выхода из цикла ? Из за того, что for может завершиться

не начавшись и переменная может быть не определена ?

Для возможности эффективной реализации компилятора - в идеале переменная цикла вне его не должна существовать. Как и сделано в Аде.

СообщениеДобавлено: 15.10.2007 11:11:45
debi12345
Bonart писал(а):
bw писал(а):Мне не нравится идея использования break в циклах, это дурной тон. Так же как continue, exit/return и пр. Точка выхода из подпрограммы должна быть одна.

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

Согласен - выходы/переходы в начало циклов соответствуют человеческой логике. Вы идете по коридору и видите дверь с надписью "выход" - и выходите, если она открыта. Не обязательно идти о конца, бесполезно проверяя остальные двери.

СообщениеДобавлено: 15.10.2007 11:28:31
bw
Это можно рассматривать как двери-порталы. Ты входишь в разные двери, но выходишь всегда из одной и той же, очень скоро твой мозг лопнет, если ты попытаешься вспомнить в какую дверь ты входил что бы выйти :-).

..bw

СообщениеДобавлено: 15.10.2007 12:39:47
Alexander
alexs писал(а):ну уж если совсем тюнинг наводить - то тогда так:


Наверное я не правильно обозвал второй вариант, слишком похоже
на просто конец в Обероне. Можно что то вроде completefor.

Код: Выделить всё
X := 20;
for f := 10 to X do begin
  WriteLn(f);
  if f = 15 then break;
breakfor; // опциональный параметр
  WriteLn('Цикл был прерван. Значение F=', f);
completefor;  // опциональный параметр
  WriteLn('А сюда бы мы попали, если бы break не было. Значение F=', f);
end; {end for}
// сюда попадаем в любом случае, если Х < 10 то F = 10.
WriteLn('Значение F=', f);


Bonart писал(а):Для возможности эффективной реализации компилятора - в идеале переменная цикла вне его не должна существовать. Как и сделано в Аде.


Понял, со значением переменной цикла после цикла проясняется.
Может как то явно указывать, если переменная цикла нужна после
цикла, нпример использовать ":=", а когда не нужна просто "=" ?
Ну равна в пределах цикла и всё тут.

alexs писал(а):аналогично строить для циклов while-do и repeat-until


Да, конечно ! А вот дать для всех одинаковое имя или для каждого своё
это вопрос. Для простоты компилятора и обучения лучше одно.
Например что то вроде complete и breaked.
Для читаемости программ - разные.

alexs писал(а):также можно отказаться от открывающего begin в циклах
for и while - но это дело вкуса лично мне они всёж нравятся (а может
привычка).


Да, либо от begin, либо наоборот от концов конструкций. Те от do,
then, ... А begin можно или сократить до 3 букв или использовать
вместо него do.

bw, какая альтернатива этому сейчас ? :

Код: Выделить всё
for f := 1 to 10 do begin
    for  ff := 1 to 10 do begin
        for  fff := 1 to 10 do begin
          if (f = 5) and (ff = 5) and (fff = 5) then goto ex;
        end;
    end;
end;

ex:

СообщениеДобавлено: 15.10.2007 13:30:08
ev
с логической точки зрения более правильнее отказаться от от do
т.к. begin и end - это границы блока
без них может выполнятся цикл
Код: Выделить всё
for  fff := 1 to 10 do
if (f = 5) and (ff = 5) and (fff = 5) then goto ex;

так же как и можно опускать begin и end в условиях и т.п.
по аналогии можно рассмотреть наличие и отсутствие { и } в циклах и условиях в си-подобных языках (например, си и пхп)

СообщениеДобавлено: 15.10.2007 14:09:39
bw
Alexander писал(а):какая альтернатива этому сейчас ?

Код: Выделить всё
function Loop1: Boolean;
begin
  I := 1;
  while I <= 10 and Loop2(I) do I += 1;
  Result := I > 10;
end;

function Loop2(I): Boolean;
begin
  J := 1;
  while J <= 10 and Loop3(I, J) do J += 1;
  Result := J > 10;
end;

function Loop3(I, J): Boolean;
begin
  K := 1;
  while K <= 10 and Expression(I, J, K) do K += 1;
  Result := K = 11;
end;

fucntion Expression(I, J, K): Boolean;
begin
  Result := I != 5 or J != 5 or K != 5;
end;

begin
  Loop1;
end.


..bw