(решено) GoTo или repeat until?

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

mishastik
незнакомец
Сообщения: 5
Зарегистрирован: 29.07.2015 21:42:47

Сообщение mishastik »

Привет всем! Интересный холивар ))) из своего опыта (пишу для встроенных систем на C немного на паскале для PC) могу сказать однозначно: никаких объективных или технических причин НЕ применять гото нет! Если посмотреть в дизасм, то можно увидеть, что те же самые циклы реализуются компилятором именно с помощью гото.
Другое дело, что читаемость кода, в котором много гото, вообще никакая. Особенно если их там много, а файл-исходник тянет под пару тысяч строк. Мне однажды достался проект в наследство, который был написан именно в таком стиле, так я был готов придушить автора. но при всём при этом код работал и работает отлично! Так что применять или нет гото - это вопрос привычки и целесообразности, и принимает его для себя каждый индивидуально.
И да, все рекомендации в учебниках по поводу гото, имеют место быть только потому, что без гото реально можно обойтись.
Аватара пользователя
Pavia
постоялец
Сообщения: 290
Зарегистрирован: 07.01.2011 11:46:51

Сообщение Pavia »

Есть такая вещь как стратегия. Так вот стратегия заключается в структурирование своего кода. Структурированный код гораздо лучше работает, так-как в нём реже ошибаются программисты. И его проще понимать, а следовательно поддерживать, сопровождать.
В-третьих код становится само документированным и даже приближаться к естественному языку.
Все доказательства приведены в книге Стива Макконела Совершенный код.

Понять это можно только спустя годы программирования Даже десятилетия, особенно когда вам приходится работать над программами с размерами 10-100 тыс строк кода.
Поэтому малоопытным программистам предлагается принять это на веру.

Вирт учил структурировать свой код. А оператор goto не относится ни к одной структуре: не к записям, ник массивам, не к деревьям. Поэтому в книгах Вирта он особо и не встречается.
А вот провокатором является Дейкстра. На самом деле это известный троль. Но тут он попал в точку.
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

Pavia писал(а):Есть такая вещь как стратегия. Так вот стратегия заключается в структурирование своего кода.

Стратегия - это логика. Массив - это не логика. Деревья - это не логика. <== Это структура.
А вот оператор GoTo - это логика и в определённых местах, она очень и очень удобна.
И самое главное в приведённом изначально примере, она упрощает: как понимание, так и общее решение данной задачи, а равно и структуру кода функции.

Pavia писал(а):Вирт учил структурировать свой код.

Этому учил не Вирт, а Менделеев (см. его таблицу).

mishastik писал(а): применять или нет гото - это вопрос привычки и целесообразности

С моей колокольни, вопрос целесообразности - применяется к каждому оператору, где-то удобнее читается: for, где-то while, где-то repeat, а где-то GoTo...

mishastik писал(а):причин НЕ применять гото нет! Если посмотреть в дизасм, то можно увидеть, что те же самые циклы реализуются компилятором именно с помощью гото.

Сказанное вообще даёт GoTo - громадный перевес в сторону его использования в приличных рамках конечно (а не при каждом удобном). И многие так говорят, я почитал другие форумы.

В общем-то я пока не вижу предъявления реальных проблем с чтением кода, или его отладкой.
А альтернативная сторона приводит только зомбированные страшилки.
Счёт уже 7 : 0 в пользу использования оператора GoTo.

поэтому, основываясь вышесказанным:

Художники посовещались и постановили, от имени Искусства, всея планеты Земля, постановляем:
Оператор GoTo, был мошенническим путём унижен и практически истреблён, а это Геноцид
и поэтому оператор GoTo - отныне и навсегда, переходит в категорию ДОБРО!


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


.
xterro
постоялец
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Сообщение xterro »

Вот пожалуйста, реальный код и реальное доказательство с пояснениями.

'fgk' будет устанавливаться по два раза, не зависимо от того, переходим на label1 или на label2, по хорошему, в конце этих меток надо дабавить ещё по одному goto на основной цикл.


Код: Выделить всё

procedure set_abcde();
begin ... end;

procedure set_fgk();
begin ... end;

var
    checked_result : boolean = false;
    test_completed : boolean = false; { некая переменная для остановки цикла }
    exit_pressed   : boolean = false;

{ инициализация }
set_abcde();
set_fgk();

while (not test_completed) and (not exit_pressed) do
begin
    checked_result := functionTest(a,b,c,d,e,f,g,k); 
    ProcessMessages; 
    if(checked_result = 1) then
        set_abcde()
    else
        set_fgk();
   
    // где-то далее:  test_completed := true
end;




Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

xterro писал(а):'fgk' будет инициализироваться по два раза, не зависимо от того, переходим на label1 или на label2, по хорошему, в конце этих меток надо дабавить ещё по одному goto на основной цикл.

Вы совсем другое написали, это вопервых добавило If в цикл, а это намного хуже GoTo. А во вторых вот этот кусочек,
должен выполняться после того как было многократное while... а не во время его исполнения.

if(checked_result = 1) then
set_abcde()
else
set_fgk();

Соответственно set_fgk(); - не инициализируется при checked_result = 1, а в примере должен инициализироваться.

Основываясь вышесказанным, в апелляции отказано, т.к. альтернатива не подготовилась. Решение художников остаётся неизменным.
xterro
постоялец
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Сообщение xterro »

И что мешает вынести условие за тело цикла?

Код: Выделить всё

while (not test_completed) and (not exit_pressed) do
begin
    checked_result := functionTest(a,b,c,d,e,f,g,k);
    ProcessMessages; 
    // где-то далее:  test_completed := true
end;

if(checked_result = 1) then begin
    set_abcde();
    set_fgk();
end
else
    set_fgk();

Это во первых, во вторых, зачем в цикле вызывать одну и туже функцию с одними и теми же значениями параметров(functionTest)?
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

xterro писал(а):зачем в цикле вызывать одну и туже функцию с одними и теми же значениями параметров(functionTest)?

Ну там многоточие стоит... это был просто пример для идентификации пользы или зла от GoTo. Касаемо примера Вашего, да он будет работать, но его реализация несколько сложнее нежели с GoTo. Более того, Вы забыли внести главный цикл, внутри которого вращается всё остальное... см. изначальный пример и другие его интерпретации. Там после инициализации снова запускается "центральный" цикл... GoTo, как раз позволяло нивелировать лишний цикл и лишний If... в примере всё вращается бесконечно, пока не будет booleanExit = true; А Ваш пример только увеличил If... и запустится только один раз, а в конце в пустую запустит инициализацию, но не запустит основной "центральный" цикл.
Последний раз редактировалось vitaly_l 01.09.2015 19:09:28, всего редактировалось 1 раз.
Mikhail
энтузиаст
Сообщения: 565
Зарегистрирован: 24.10.2013 16:06:47

Сообщение Mikhail »

Goto зло при неправильном применении, поэтому для новичков на него наложено табу.
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

Mikhail писал(а):Goto зло при неправильном применении, поэтому для новичков на него наложено табу.

Если только с точки зрения, процесса обучения, то согласен. Пока мозг осваивается GoTo - сложна для понимания и может подвесить неподготовленный мозг на месяц, а иногда и на всю жизнь.
Mikhail
энтузиаст
Сообщения: 565
Зарегистрирован: 24.10.2013 16:06:47

Сообщение Mikhail »

vitaly_l писал(а):Если только с точки зрения, процесса обучения, то согласен.

Не только во время обучения, еще опыта набраться и тогда вопросы, заданные Вами, просто не возникнут.
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

Mikhail писал(а):Не только во время обучения, еще опыта набраться и тогда вопросы, заданные Вами, просто не возникнут.

Словоблудие. Пример заменяющего кода в студию, предъявите, если пример будет достойным победа за Вами, если нет - Вашему слову грош цена.
Функция в самом начале топика, попробуйте реализовать, а мы посмотрим на опыт мастера. По рукам?
Mikhail
энтузиаст
Сообщения: 565
Зарегистрирован: 24.10.2013 16:06:47

Сообщение Mikhail »

Ну, например так... :roll:

Код: Выделить всё

while True do begin
 а := 'Задаётся заново только для labelGoTo1';
 b := 'Задаётся заново только для labelGoTo1';
 c := 'Задаётся заново только для labelGoTo1';
 d := 'Задаётся заново только для labelGoTo1';
 e := 'Задаётся заново только для labelGoTo1';
 
 repeat
  f := 'Одинаковое для labelGoTo1 и labelGoTo2';
  g := 'Одинаковое для labelGoTo1 и labelGoTo2';
  k := 'Одинаковое для labelGoTo1 и labelGoTo2';

  repeat   
   ...     
   test := functionTest(a,b,c,d,e,f,g,k);
   if buttonExit then
    exit;
   ProcessMessages;
  until someGlobalBoolean;
 until  test = 1;
end;{while}


Кстати, на будущее, вот такая запись тоже неграмотна

Код: Выделить всё

if buttonExit = True then...

следует просто писать

Код: Выделить всё

if buttonExit then...
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

не компилируя программу кто скажет какой будет результат выполнения?

Код: Выделить всё

procedure Test;
var
  i : integer;
label
   loop1, loop2;
begin
  for i:=1 to 20 do begin
    loop1:
    writeln('* ', i);
    if i = 5 then goto loop2; 
  end;

  for i:=1 to 20 do  begin
    loop2:
    writeln('> ', i);
    if i=10 then goto loop1;
  end;

end;


begin
  Test;
end.
Аватара пользователя
Pavia
постоялец
Сообщения: 290
Зарегистрирован: 07.01.2011 11:46:51

Сообщение Pavia »

По опыту могу сказать что эту функцию надо заменить минимум на 3. Она будет лучше читаться и от goto избавимся.
Но для этого надо понимать что делает функция, а по огрызкам тут ничего не сделаешь.
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

А так же усложнённый вариант №2 оной же

Код: Выделить всё

procedure Test;
var
  i,j : integer;
label
   loop1, loop2;
begin
  for i:=1 to 20 do begin
    loop1:
    writeln('* ', i);
    if i = 5 then goto loop2; 
  end;

  for j:=1 to 20 do begin
    loop2:
    writeln('> ', j);
    if j=10 then goto loop1;
  end;

end;


begin
  Test;
end.
Ответить