Здравствуйте, McSeem2, Вы писали:
MS>Я бы сказал, что использование goto в стиле Фортрана-4 — это маразм. Однако, полный запрет goto — это тоже маразм. Народу не нужен нездоровый фанатизм. Народу нужен здоровый фанатизм.
Вы подходите к вопросу слишком рационально. Между тем, если изучить постинги по этому вопросу, станет очевидным, что с этим оператором дело не чисто. Он скверен, как число 13, как представитель касты неприкасаемых. Его использование — это ересь, за которую следует отлучать от интернета.
Здравствуйте, kan_izh, Вы писали:
_>for(xmlNodePtr c = parent->children; c; c = c->nextSibling) _>{ _> if(c->type == NODE_TEXT) continue; _> if(c->namespace != myNamespace) continue; _>... _>} _>[/ccode] _>В таком коде такой неявный брэйк нельзя сделать. А замена несколько continue будет порождать глубокую вложенность if.
По моему, даже самая наиглубочайшая вложенность IF — и то лучше чем один единственный continue по той простой причине, что код содержащий в себе слова continue невозможно оформить в виде отдельной процедуры.
Кстати, зачастую, всё множество вложенных IF-ов можно заменить одним единственным:
for(xmlNodePtr c = parent->children; c; c = c->nextSibling)
{
if ((c->type != NODE_TEXT) && (c->namespace == myNamespace) && (...) && (...) && (...) && (...) ...)
{
...
}
}
или ещё лучше так:
for(xmlNodePtr c = parent->children; c; c = c->nextSibling)
{
if (IsThisGood(c))
{
...
}
}
Сергей Губанов wrote:
> _>for(xmlNodePtr c = parent->children; c; c = c->nextSibling) > _>{ > _> if(c->type == NODE_TEXT) continue; > _> if(c->namespace != myNamespace) continue; > _>... > _>} > _>[/ccode] > _>В таком коде такой неявный брэйк нельзя сделать. А замена несколько > continue будет порождать глубокую вложенность if. > > По моему, даже самая наиглубочайшая вложенность IF — и то лучше чем один > единственный continue по той простой причине, что код содержащий в себе > слова continue невозможно оформить в виде отдельной процедуры.
Вообще говоря, различие исключительно синтаксическое, continue — всего лишь sugar, насколько оправдано использование
сахара — не знаю, диабетикам, конечно, вредно, но это не означает, что его нужно запретить вообще.
Так что почему невозможно? Не сложнее, чем куча вложенных if-ов. И делается довольно просто — все continue заменяются на
"return false", в конце, где нет continue — return true, а вместо блока, содержащего continue-ы ставим
if(!checkContinues(i)) continue;
или
if(chechContinues(i))
{
...
}
по вкусу.
> Кстати, зачастую, всё множество вложенных IF-ов можно заменить одним > единственным: > > for(xmlNodePtr c = parent->children; c; c = c->nextSibling) > { > if ((c->type != NODE_TEXT) && (c->namespace == myNamespace) && (...) && (...) && (...) && (...) ...) > { > ... > } > } >
Насколько оправданно писать всё в одну строчку (точнее оператор)?..
> или ещё лучше так: > > for(xmlNodePtr c = parent->children; c; c = c->nextSibling) > { > if (IsThisGood(c)) > { > ... > } > }
Чем это хуже?
for(...)
{
if(!IsThisGood(c)) continue;
...
}
Мне, честно говоря, так больше нравится — меньше вложенность {}.
Ладно, в общем, continue — да, легко обходится (даже можно запретить требованиями corporation code style). А что делать
с break? Насколько это мне представляется, это можно обойти только введением специального флага, что засоряет синтаксис.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, zzzale, Вы писали:
Z>Я имею в виду случаи когда ДЕЙСТВИТЕЛЬНО была необходимость применять этот оператор (желательно с примером и описанием ПО).
Во времена Windows 3.x исходник DefWindowProc был опубликован. И там было такое
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>Ну, во-первых, я в таких местах всегда пишу комментарий типа "exit the loop", а во-вторых — как я писал это чисто иррациональное, а не мотивированное большей читабельностью кода. Ну вот заскок у меня такой. Просто иногда бывает "не в тему" заводить очередную булеву переменную, значение которой проверяется наряду с "основным" условием цикла.
SDB>P.S. SDB>Посто мой был собственно в поддержку "некоторых", на которых ссылался Cyberax.
В Вашем примере:
for (int i = 0; i < 10; ++i)
{
...
if (some_rare_contition)
{
i = 10; // неявный break :)
}
else {
...
}
}
в случае если потребуется изменить количество итераций цикла — надо будет менять две строчки кода. Есть некоторая вероятность, что вы забудете это сделать. А когда начнёте искать ошибку, то этот комментарий "exit the loop" будет сбивать с толку, т.к. сообщает, что здесь выход из цикла.
Здравствуйте, zzzale, Вы писали:
Z>в случае если потребуется изменить количество итераций цикла — надо будет менять две строчки кода. Есть некоторая вероятность, что вы забудете это сделать. А когда начнёте искать ошибку, то этот комментарий "exit the loop" будет сбивать с толку, т.к. сообщает, что здесь выход из цикла.
Еще раз подчеркну, что не считаю этот код "идеальным" и "образцовым".
[ posted via RSDN@Home 1.1.4 stable SR1 r568, accompanied by silence ]
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Во времена Windows 3.x исходник DefWindowProc был опубликован. И там было такое
PD>goto ICantBelieveThatIUserAGotoStatement;
Мне когда-то преподаватель показывал примеры на WinAPI, когда следовало применять goto.
Что-то вроде:
void fun()
{
//... действияif(ошибка)goto end_fun;
//... снова действия
//вложенный ifif(что-то)goto end_fin;
//и опять в том же духе.
normal:
//что-то сделать
end_fun:
//что-то сделать
}
Здравствуйте, zzzale, Вы писали:
Z>Мне когда-то преподаватель показывал примеры на WinAPI, когда следовало применять goto. Z>Что-то вроде:
Z>
Z>void fun()
Z>{
Z> //... действия
Z> if(ошибка)goto end_fun;
Z> //... снова действия
Z> //вложенный if
Z> if(что-то)goto end_fin;
Z> //и опять в том же духе.
Z> normal:
Z> //что-то сделать
Z> end_fun:
Z> //что-то сделать
Z>}
Z>
Не всегда стоит слушать преподавателей.
void
func()
{
do
{
if ( error1 )
break;
if ( error2 )
break;
// well, no errors, do other stuff and exitreturn;
}
while (0);
// вышли брейком
// обрабатываем ошибку здесь
}
Здравствуйте, kan_izh, Вы писали:
_>Ладно, в общем, continue — да, легко обходится (даже можно запретить требованиями corporation code style). _>А что делать с break?
Ничего не делать, break ни в чём не виноват. Его только нельзя использовать внутри WHILE-DO-END и REPEAT-UNTIL циклов по определению этих циклов. Внутри безусловного цикла LOOP-END инструкция break (т.е. EXIT) — единственный способ завершения цикла.
P. S. В Си-образных языках безусловный цикл LOOP-END синтаксически обычно записывается как: while (true) {...}.
Здравствуйте, Kluev, Вы писали:
K>Не всегда стоит слушать преподавателей.
K>
K>void
K> func()
K>{
K> do
K> {
K> if ( error1 )
K> break;
K> if ( error2 )
K> break;
K> // well, no errors, do other stuff and exit
K> return;
K> }
K> while (0);
K> // вышли брейком
K> // обрабатываем ошибку здесь
K>}
K>
Мне тоже пример показался не самым лучшим.
Более точнее: Z>void fun() Z>{ Z> //... действия Z> if(ошибка)goto end_fun;
Z> //... снова действия Z> //вложенный if
for(...) Z> {
//...
if(что-то)goto end_fin;
//...
}
Z> //и опять в том же духе.
Z> normal: Z> //что-то сделать Z> end_fun: Z> //что-то сделать Z>} Z>
Совсем забыл. Зацените else-clause у циклов в питоне. else у цикла не выполяется, если цикл был прерван по break. Сильно подозреваю, что в питоне это сделано специально для решения типичной проблемы временной переменной-флага. Вот пример: если данные уже есть в массиве, то добавлять не надо, в противном случае — их надо добавить:
// всем знакомый паттернbool f = false;
for (unsigned i = 0; i < array.size(); ++i)
{
if (array[i] == data)
{
f = true;
break;
}
}
if (!f) array.push_back(data);
for (unsigned i = 0; i < array.size(); ++i)
{
if (array[i] == data)
break;
}
else array.push_back(data);
Здравствуйте, Кодёнок, Вы писали:
Кё>Совсем забыл. Зацените else-clause у циклов в питоне. else у цикла не выполяется, если цикл был прерван по break. Сильно подозреваю, что в питоне это сделано специально для решения типичной проблемы временной переменной-флага. Вот пример: если данные уже есть в массиве, то добавлять не надо, в противном случае — их надо добавить:
Плохое решение. В таких случаях нужна декомпозиция.
bool Contains(Array const& array, Data const& data)
{
for (unsigned i = 0; i < array.size(); ++i)
if (array[i] == data)
return true;
retrun false;
}
if (!Contains(array, data))
array.push_back(data);
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Olivan, Вы писали:
O>Кстати, пример для упражнения
... O>я бы всё-таки переписал с использованием флага:
... O>кода столько же, но имхо так читабельней.
Пора бы и прекратить предлагать иные варианты решения. Ведь, вообще-то, это
классическая задача линейного поиска имеющая каноническое решение:
СГ>i := 0; СГ>WHILE (i < N) & условие(i) DO INC(i) END; СГ>IF i < N THEN условие под номером i не выполнено END
А если проверка условия состоит из 10 инструкций и не может быть записана выражением? А зависимость этих 10 инструкций от локальных переменных затруднит выделение его в локальную функцию? Для Оберона это особенно актуально.