Re[4]: В чем прелесть замаскированного goto?
От: enji  
Дата: 08.09.10 21:04
Оценка: +3 -1
Здравствуйте, qqqqq, Вы писали:

Q>Я даже не могу понять, как еще можно было написать алгоритм, который читает и обрабатывает какие-то там данные будь то из сокета или из файла, если не известно сколько их там и надо обрабатывать ошибки. Можно, конечно, вместо тех break-ов поставить условия в операторы циклов или поменять условия наоборот вместо continue, но иногда это не делают по разным причинам. По мне, так особенно большой связи с гото не наблюдается, за исключением того, что все нетривиальные нелинеиные программы в конечном счете набор операций и jump-ов из одного места в другое, как и гото.


Эт ясно. У вас есть цикл, в нем вам нужны break\continue; они есть в языке, пользуйтесь. Но когда у вас нет цикла и вам нужен goto, то зачем изобретать do { ... if () break; .... } while(false) или аналог на switch(0)case 0: ? Почему не признаться — да, мне нужен goto?

Чем
do
{
  func1();
  if (func2()) break;
  func3();
  if (func4()) break;
  func5();
} while (false);

лучше
{
  func1();
  if (func2()) goto end_job;
  func3();
  if (func4()) goto end_job;
  func5();
end_job:
}
Re[2]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 08.09.10 21:46
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>goto по своей природе слишком "мощный". Если я вижу break, я точно знаю, что переход произойдёт в конец текущего блока-цикла. Если я вижу goto, то знаю, что перейти он может куда угодно, и восприятие кода сразу усложняется. Кроме того, с goto легче допустить какой-нибудь ляпсус, воткнув пару операций между концом блока и меткой, или просто опечатавшись каким-нибудь CYCLE1_END вместо CYCLE2_END, а потом удивляться, чего это поток управления скачет по всей функции взад-вперёд.


стоп-стоп-стоп!
Откуда таки у тебя вдруг возникло много меток? Возможность перейти не туда и т. д?
У нас в оригинальном коде была одна точка для выхода из блока? Вот и у goto будет ОДНА метка...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: объект-механизм
От: Erop Россия  
Дата: 08.09.10 21:53
Оценка:
Здравствуйте, fk0, Вы писали:


fk0> Для этого нужны вложенные фунцкии, как в паскале. Для одептов GCC и Delphi, для виндоморонов и C++ -- никак нельзя.

Да ладно уж прямо вот и никак
Автор: Erop
Дата: 26.08.05
?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: В чем прелесть замаскированного goto?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 08.09.10 21:55
Оценка: +2
Здравствуйте, Erop, Вы писали:

CF>>goto по своей природе слишком "мощный". Если я вижу break, я точно знаю, что переход произойдёт в конец текущего блока-цикла. Если я вижу goto, то знаю, что перейти он может куда угодно, и восприятие кода сразу усложняется. Кроме того, с goto легче допустить какой-нибудь ляпсус, воткнув пару операций между концом блока и меткой, или просто опечатавшись каким-нибудь CYCLE1_END вместо CYCLE2_END, а потом удивляться, чего это поток управления скачет по всей функции взад-вперёд.


E>стоп-стоп-стоп!

E>Откуда таки у тебя вдруг возникло много меток? Возможность перейти не туда и т. д?
E>У нас в оригинальном коде была одна точка для выхода из блока? Вот и у goto будет ОДНА метка...

Точка одна, но блоков-то таких может быть несколько. И у каждого будет своя метка выхода. Опечатался — попал в точку выхода не того блока, и здравствуй, отладка.
Кроме того, проблема не только во множественности меток, но и в отсутствии каких-либо гарантий относительно их местоположении (чуть подробнее описал здесь
Автор: CaptainFlint
Дата: 09.09.10
).
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[5]: В чем прелесть замаскированного goto?
От: c-smile Канада http://terrainformatica.com
Дата: 08.09.10 22:15
Оценка:
Здравствуйте, enji, Вы писали:

E>
E>{
E>  func1();
E>  if (func2()) goto end_job;
E>  func3();
E>  if (func4()) goto end_job;
E>  func5();
E>end_job:
E>}
E>


Вот это скомпилировать не получится:

{
  func1();
  if (func2()) goto end_job;
  std::string name = func3();
  if (name != "ok") goto end_job;
  func5();
end_job:
}


Придется писать как-то так:

{
func1();
if (func2()) goto end_job;
std::string name = func3();
if (name != "ok") goto end_job;
func5();
}
end_job:;

Что есть вельми грустный вариант. Во всяком случае ничем не лучше чем do {} while(false);
Re: В чем прелесть замаскированного goto?
От: A.Lokotkov Россия http://www.linkedin.com/pub/alexander-lokotkov/a/701/625
Дата: 09.09.10 05:36
Оценка: :)
Здравствуйте, enji, Вы писали:

E>Собственно вопрос — чем такой код лучше goto?


Если пишем на голом Си, то при помощи такой конструкции можно легко реализовать откат, скажем, многоступенчатой инициализации, инкрементируя номер каждой успешной стадии. После while(0), в случае неудачи где-нибудь посреди do{}while(0), стадии легко откручиваются обратно при помощи switch по номеру стадии без break-ов внутри.
bloß it hudla
Re: В чем прелесть замаскированного goto?
От: Mr.Cat  
Дата: 09.09.10 07:50
Оценка:
Здравствуйте, enji, Вы писали:
E>Собственно вопрос — чем такой код лучше goto?
for(;) { break } — это примитив структурного программирования (безусловный цикл). Тем и лучше.
Re[4]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 08:25
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>Кроме того, если не нравится цикл, можно его замаскировать под блок какими-нибудь дефайнами типа BLOCK_BEGIN (do), BLOCK_END (while(0)), BLOCK_EXIT (break). Это скорее вопрос привычки и личного восприятия.


Это ЕЩЁ ХУЖЕ для поддержки. Так тебе надо въехать в то, что цикл -- это на самом деле не цикл. А так сначала надо будет найти и понять эти макросы, а потом въехать, что цикл -- это не цикл
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 08:28
Оценка: 1 (1) +1 :)
Здравствуйте, CaptainFlint, Вы писали:

CF>...Да, её можно назвать END_OF_CYCLE,

Боже мой!!! Какой такой цикл? В этом коде НЕТ НИКАКОГО ЦИКЛА!!!

CF>да, её можно расположить в конце цикла. Но можно ведь и не располагать, вот в чём проблема. И читатель кода, пока явным образом не полезет и не найдёт точное расположение метки, не может быть уверенным, что программист воткнул эту метку куда надо было, а не куда захотелось его левой пятке.


А ещё можно все функции и переменные в программе назвать НЕПРАВИЛЬНО!

Нет бы вот назвать метку ПОНЯТНО, и расположить где надо. Получится простой С++, практически простой С-код. СРАЗУ ЖЕ ПОНЯТНЫЙ при поддержке.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 08:39
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>Точка одна, но блоков-то таких может быть несколько. И у каждого будет своя метка выхода. Опечатался — попал в точку выхода не того блока, и здравствуй, отладка.


Проще надо писать функции. ПРОЩЕ! Короче, понятнее...
И идентификаторы выбирать осмысленные, а не var1, var2, var3...

Лучше всего, чтобы одна функция делала ОДНО дело. То есть код
void foo() 
{
    MyObj* theObj = 0;
    {   // Search object
         if( cond1_1 ) {
             theObj = ...;
             goto endOfSearchObj;
         }
         if( cond1_2 ) {
             theObj = ...;
             goto endOfSearchObj;
         }
         if( cond1_3 ) {
             theObj = ...;
             goto endOfSearchObj;
         }
    }
endOfSearchObj: ;
    // тут какой-то хитрый эпилог поиска, из-за которого goto вообще понадобился
    assert( theObj != 0 ); 

    {   // process theObj
         if( cond2_1 ) {
             // process theObj...
             goto endOfProcessObj;
         }
         if( cond2_2 ) {
             // process theObj...
             goto endOfProcessObj;
         }
         if( cond2_3 ) {
             // process theObj...
             goto endOfProcessObj;
         }
    }
endOfProcessObj: ;
    // тут какой-то хитрый эпилог обработки, из-за которого goto вообще понадобился
}
лучше всего оформить как-то так:
MyObj* findObj()
{
    MyObj* theObj = 0;
    {   // Search object
         if( cond1_1 ) {
             theObj = ...;
             goto endOfSearchObj;
         }
         if( cond1_2 ) {
             theObj = ...;
             goto endOfSearchObj;
         }
         if( cond1_3 ) {
             theObj = ...;
             goto endOfSearchObj;
         }
    }
endOfSearchObj: ;
    // тут какой-то хитрый эпилог поиска, из-за которого goto вообще понадобился
    assert( theObj != 0 ); 
    return theObj;
}

MyObj* processObj( MyObj* theObj ) 
{
    {   // process theObj
         if( cond2_1 ) {
             // process theObj...
             goto endOfProcessObj;
         }
         if( cond2_2 ) {
             // process theObj...
             goto endOfProcessObj;
         }
         if( cond2_3 ) {
             // process theObj...
             goto endOfProcessObj;
         }
    }
endOfProcessObj: ;
    // тут какой-то хитрый эпилог обработки, из-за которого goto вообще понадобился
}
void foo() 
{
    processObj( findObj() );
}
а ещёлучше в виде объекта-механизма...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: В ЭТОЙ ПРОГРАММЕ НЕТ НИКАКОГО ЦИКЛА!!!
От: Erop Россия  
Дата: 09.09.10 08:41
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>for(;) { break } — это примитив структурного программирования (безусловный цикл). Тем и лучше.

Чего?
В ЭТОЙ ПРОГРАММЕ НЕТ НИКАКОГО ЦИКЛА!!!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 08:56
Оценка:
Здравствуйте, A.Lokotkov, Вы писали:

AL>Если пишем на голом Си, то при помощи такой конструкции можно легко реализовать откат, скажем, многоступенчатой инициализации, инкрементируя номер каждой успешной стадии. После while(0), в случае неудачи где-нибудь посреди do{}while(0), стадии легко откручиваются обратно при помощи switch по номеру стадии без break-ов внутри.


Ну и с goto можно точно так же...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: В чем прелесть замаскированного goto?
От: Nik_1 Россия  
Дата: 09.09.10 09:14
Оценка: 1 (1) +1
Здравствуйте, enji, Вы писали:
E>Собственно вопрос — чем такой код лучше goto?
Лучше структурированностью кода. В случаи брейк ты точно знаешь, что это переход к концу текущего блока. Приэтом при покидании блока корректно освободятся локальные переменные блока.
В случаи гоуту это посыл програмиста неизвестно куда. Чтоб найти куда послали — нодо сначало "погуглить" по коду эту метку. Приэтом логика кода будет сильней запутана, если начнут встречаться переходы из внутренностей одного блока в другой.
E>Я в курсе, что goto стоит избегать и согласен с этим, но зачем его маскировать циклами или switch? Все же goto встроен в С/С++, а идиома "цикл, который выполняется 1 раз" — какая-то искусственная...
Он здесь не маскируется. Это принципиально другой подход, который лучше чем использование гоуту. Брейк — это досрочное прерывание текущей последовательности действий. Гоуту — это некоторый посыл фигзнает куда.
Re[3]: В чем прелесть замаскированного goto?
От: A.Lokotkov Россия http://www.linkedin.com/pub/alexander-lokotkov/a/701/625
Дата: 09.09.10 09:30
Оценка:
Здравствуйте, Erop, Вы писали:

E>Ну и с goto можно точно так же...


С goto можно, конечно, но не так красиво, кмк, ибо появляется лишняя именованная сущность (метка). По моему опыту, если нескольким разработчикам разрешено использовать goto для реализации подобных конструкций, рано или поздно кто-нибудь рожает фрагмент с абсолютно нечитабельным control flow.
bloß it hudla
Re[3]: В ЭТОЙ ПРОГРАММЕ НЕТ НИКАКОГО ЦИКЛА!!!
От: Mr.Cat  
Дата: 09.09.10 09:38
Оценка:
Здравствуйте, Erop, Вы писали:
MC>>for(;) { break } — это примитив структурного программирования (безусловный цикл). Тем и лучше.
E>Чего?
E>В ЭТОЙ ПРОГРАММЕ НЕТ НИКАКОГО ЦИКЛА!!!
Если ты про break, я имел в виду, еснно if() break; или if() continue; break.
Re[5]: В чем прелесть замаскированного goto?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 09.09.10 10:31
Оценка: 1 (1)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, CaptainFlint, Вы писали:


CF>>...Да, её можно назвать END_OF_CYCLE,

E>Боже мой!!! Какой такой цикл? В этом коде НЕТ НИКАКОГО ЦИКЛА!!!

Да ради Бога, назовём END_OF_BLOCK. Слово "цикл" я использовал исключительно из-за использования "цикловых" синтаксический конструкций языка. На суть моего поста это не влияет ни в малейшей степени, чего придираться по мелочам?

CF>>да, её можно расположить в конце цикла. Но можно ведь и не располагать, вот в чём проблема. И читатель кода, пока явным образом не полезет и не найдёт точное расположение метки, не может быть уверенным, что программист воткнул эту метку куда надо было, а не куда захотелось его левой пятке.


E>А ещё можно все функции и переменные в программе назвать НЕПРАВИЛЬНО!


E>Нет бы вот назвать метку ПОНЯТНО, и расположить где надо. Получится простой С++, практически простой С-код. СРАЗУ ЖЕ ПОНЯТНЫЙ при поддержке.


Так, меня всё-таки не поняли. Попробую зайти с другой стороны.
Вот я написал код. Метки понятные, расположены где надо, переменные названы вразумительно, — короче, поддерживай да радуйся. НО! Тот человек, который по каким-то причинам получил мой код для разбора и поддержки, — он-то не знает, что я располагал всё правильно, называл всё грамотно. Он видит goto на какую-то метку. Пусть даже эта метка названа так, что совершенно очевидно, что она располагается в конце текущего блока. Но очевидное название — это не гарантия. Она может располагаться и в другом месте. И тот человек, не будучи уверенным в качестве моего кода, вынужден сам, своими ручками искать метку и убеждаться, что да, она поставлена ровно там, где должна быть поставлена.

Оператор break лишён этого недостатка. Даже если я пишу невероятно криво (ну, не считая #define break, конечно), любой человек, читающий код, будет точно и с абсолютной гарантией знать: да, break выходит из текущего цикла. Таким образом, если я использую goto, я добавляю потенциальному "поддерживателю" моего кода неуверенностей и необходимости лишних действий для проверки неких предпосылок. Если же я использую break, поведение регулируется уже не мной, а самим языком, значит, "поддерживатель" меньше зависит от моих выкрутасов, следовательно, ему не придётся гадать, грамотно я писал или нет.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[5]: В чем прелесть замаскированного goto?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 09.09.10 10:35
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, CaptainFlint, Вы писали:


CF>>Кроме того, если не нравится цикл, можно его замаскировать под блок какими-нибудь дефайнами типа BLOCK_BEGIN (do), BLOCK_END (while(0)), BLOCK_EXIT (break). Это скорее вопрос привычки и личного восприятия.


E>Это ЕЩЁ ХУЖЕ для поддержки. Так тебе надо въехать в то, что цикл -- это на самом деле не цикл. А так сначала надо будет найти и понять эти макросы, а потом въехать, что цикл -- это не цикл


Гм… Возможно, у нас разные способы чтения кода, но если я увижу код
BLOCK_BEGIN
{
    if (smth)
        BLOCK_EXIT;
    if (smth_else)
        BLOCK_EXIT;
    do_smth_useful();
}
BLOCK_END

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

Или ты никогда сторонними библиотеками не пользовался? В MFC ты первым делом бросаешься разгребать, во что задефайнены все эти жуткие DECLARE_DYNAMIC, BEGIN_MESSAGE_MAP, END_MESSAGE_MAP, и как они работают? А в Qt не станешь изучать программу, пока досконально не разберёшься, какой промежуточный C++-код генерируется из отсутствующих в синтаксисе языка сигналов и слотов?
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[4]: В ЭТОЙ ПРОГРАММЕ НЕТ НИКАКОГО ЦИКЛА!!!
От: Erop Россия  
Дата: 09.09.10 12:02
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>>>for( ; ; ) { break } — это примитив структурного программирования (безусловный цикл). Тем и лучше.

E>>Чего?
E>>В ЭТОЙ ПРОГРАММЕ НЕТ НИКАКОГО ЦИКЛА!!!
MC>Если ты про break, я имел в виду, еснно if() break; или if() continue; break.
Я про то, что эта ваша "конструкция" вводит всех в заблуждение, показывая тут цикл, хотя цикла никакого как раз и нет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 12:09
Оценка: :)
Здравствуйте, A.Lokotkov, Вы писали:

AL>С goto можно, конечно, но не так красиво, кмк,


А тебе какой-то из обсуждаемых тут вариантов (что этот цикл-не цикл, что блок с досрочным выходом по goto, что switch, который не switch) кажется красивым?

AL>ибо появляется лишняя именованная сущность (метка).

В альтернативном варианте получается лишний цикл...
Метке-то хотя бы имя понятное можно дать

AL>По моему опыту, если нескольким разработчикам разрешено использовать goto для реализации подобных конструкций, рано или поздно кто-нибудь рожает фрагмент с абсолютно нечитабельным control flow.

По моему опыту, чем менее стандартные и прямые конструкции разрешишь юзать таким разработчикам, тем дольше потом разгребать

Что касается конкретно использования goto, макросов и прочих спорных конструкций, то мой опыт говорит мне, что хорошо работает такое правило, что их использование нужно согласовать с начальником. Обычно этого достаточно, чтобы природная лень подвигала людей на поиск нормальных решений...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 12:28
Оценка:
Здравствуйте, Nik_1, Вы писали:

N_>Приэтом логика кода будет сильней запутана, если начнут встречаться переходы из внутренностей одного блока в другой.


А вот и не надо использовать goto из внутренностей одного блока ВО ВНУТРЕННОСТИ другого. И goto назада не надо.
Надо goto наружу блока, непосредственно за его конец!

E>>Я в курсе, что goto стоит избегать и согласен с этим, но зачем его маскировать циклами или switch? Все же goto встроен в С/С++, а идиома "цикл, который выполняется 1 раз" — какая-то искусственная...

N_>Он здесь не маскируется. Это принципиально другой подход, который лучше чем использование гоуту. Брейк — это досрочное прерывание текущей последовательности действий. Гоуту — это некоторый посыл фигзнает куда.

Вот объясни мне, почему тебе конструкция
do { // Обработка команд сервера
   if( обычный_случай ) {
       // ...
       break;
   }
} while( 0 );

кажется понятнее, чем
{ // Обработка команд сервера 
   if( обычный_случай ) {
       // ...
       goto endOfServerCommansProcess;
   }
}
endOfServerCommansProcess:;

При ответе учти, пожалуйста, что конструкция с goto стандартная, а стандартная конструкция с циклом выглядит так:
do { // Обработка команд сервера
   if( необычный_случай ) {
       // ...
       break;
   }
} while( условие_продолжения );


При этом нестандартное использование цикла происходит без объявления войны. Вот мы читаем код какой-то функции, видим цикл, и пока до while не дочитаем, про то, что это нифига не цикл так и не узнаем
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.