-
> а FixInsight по этому поводу что-то ищет/предупреждает ?
Нет. Надо будет добавить :)
-
> Kerk © (25.05.16 15:28) [60]
> Нет. Надо будет добавить :)
Использование GOTO не ошибка, не о чем тут предупреждать. Не, ну можно, конечно, в предупреждении выводить "Ошибка #100500 Не совпадение с мнением Kerka-а насчет идеального кода" :)
-
> Внук © (25.05.16 15:14) [59]
В Джаве есть: break метка continue метка
По сути - те же goto. Причем сначала их не было, а в какой-то версии - появились. Значит, необходимость в них все же есть - и это тоже аргумент.
-
> DVM © (25.05.16 15:33) [61] > > > Kerk © (25.05.16 15:28) [60] > > > Нет. Надо будет добавить :) > > Использование GOTO не ошибка, не о чем тут предупреждать. > > Не, ну можно, конечно, в предупреждении выводить "Ошибка > #100500 Не совпадение с мнением Kerka-а насчет идеального > кода" :)
Так в этом же вся суть проекта! :)
Если серьезно, то кроме потенциальных ошибок там еще есть реагирование на стилевые особенности кода. Слишком длинные методы, слишком большое количество переменных, вложенные with и т.п. Goto хороший кандидат туда же. Тем более что любую проверку можно легко отключить.
-
> Юрий Зотов © (25.05.16 15:34) [62]
Так я про это написал в [45]. Операторы прерывания циклов с метками убили смысл goto совсем. Там, где они поддерживаются, конечно.
-
вот такой код
procedure TForm1.Button1Click(Sender: TObject); label lbl; begin try goto lbl; finally ShowMessage('1'); end; lbl: ShowMessage('2'); end; у меня не компилируется, выдает ошибку [dcc32 Error] Unit1.pas(36): E2127 'GOTO lbl' leads into or out of TRY statement, or out of FOR-IN statement whose enumerator has destructor
в вот такой
procedure TForm1.Button2Click(Sender: TObject); var I: Integer; begin for I := 0 to 10 do begin try if I > 5 then Break; finally OutputDebugString(PChar(I.ToString)); end; end; end; компилируется.
так что label не так близок к break, continue и exit, как кажется.
-
Попробую суммировать все высказывания со своей колокольни. Goto сам по себе ничем не вреден. Он всего лишь инструмент, которым надо уметь пользоваться. Если им пользуется тот кто умеет, инструмент может иногда помочь сделать код более удобным/более читаемым/более понятным. Если им пользуются троешники, то там "как повезёт".
-
> Германн © (26.05.16 01:27) [66]
Ну вот к чему это переливание из пустого в порожнее? Ты реально думаешь, что кто-то из присутствующих в этой ветке, в том числе те, кто против использования goto, не умеют им пользоваться? В плоскости умеет/не умеет тут вопрос даже не стоит.
-
А почему никто не сказал, что на метку можно перейти из множества мест? Или в Делфи это не так?
-
> Операторы break и continue ведь тоже частные случаи goto
А если бы при помощи операторов break и continue догадались дать возможность прервать несколько циклов за раз, им бы цены не было. Но ведь мир далеко не идеален и для прерывания нескольких циклов нормальной простой и понятной альтернативы goto нет. Исключения, замыкания, анонимные методы - не панацея, лучше и проще они не сделают никогда. А вот написать Break(2) - как было бы классно. В моём собственном скриптовом языке такое реализовано и метки действительно стали вообще не нужны.
-
Dimka Maslov © (26.05.16 09:31) [69]
"А вот написать Break(2) - как было бы классно"
На мой взгляд, это намного хуже goto. Возможностей меньше, а побочные явления в циклах те же.
-
> Владислав © (26.05.16 09:39) [70]
С чего это вдруг "возможностей меньше, а побочные явления те же". Возможности те же, но "читабельность" сохраняется. Метки и переходы не нужны. Как не нужна лишняя писанина. В таких языках, как C++, где break ещё из switch выводит - вообще была бы песня.
Вот такая конструкция у меня прекрасно работает без побочных эффектов
#func check(i, j) #if (i == 2) & (j == 2) then break(2) #endfunc
#for i = 1 to 5 #for j = 1 to 5 #check(i, j) #next #next
Давайте попробуем повторить такое же в Delphi... Даже goto не поможет И не надо говорить, что у break для нескольких циклов возможностей меньше.
-
> Dimka Maslov © (26.05.16 11:03) [71]
А так будет работать?
#func check3(i, j) #if (i == 2) & (j == 2) then break(2) #endfunc
#func check2(i, j) #check3(i, j) #endfunc
#func check1(i, j) #check2(i, j) #endfunc
#func check(i, j) #check1(i, j) #endfunc
#for i = 1 to 5 #for j = 1 to 5 #check(i, j) #next #next
-
> Давайте попробуем повторить такое же в Delphi... > Даже goto не поможет
Еще как поможет.
function Check(i, j: integer): boolean; begin result := (i = 2) and (j = 2) end;
for i := 1 to 5 do for j := 1 to 5 do if Check(i, j) then goto lbl; lbl: ...
-
> Dimka Maslov © (26.05.16 11:03) [71]
И, кстати, Ваш подход, когда "уровень возврата" (двойка) зашит в тело самой функции, чреват ошибками. Стоит лишь вызвать ее из места, где уровень вложенности другой (не двойка). Поэтому программер, вызывая функцию, должен всегда это контролировать, а еще должен знать код функции. Все это и неудобно, и опасно.
-
Вот так и удобнее, и универсально, и безопасно:
#func check(i, j, n)
#if (i == 2) & (j == 2) then break(n)
#endfunc
#for i = 1 to 5
#for j = 1 to 5
#check(i, j, 2)
#next
#next
-
> А так будет работать?
Будет. На уровне интерпретатора это реализовано через исключение.
> Юрий Зотов © (26.05.16 11:45) [74]
Это просто пример. Обычно, всё же до таких вещей не надо доходить. Достаточно и просто прерывать не сколько циклов. А ещё бывает удобно вложенный цикл прервать, а у внешнего сразу начать новую итерацию, т.е. иметь возможность ещё continue(n) использовать. Вот тут уже никакие goto точно не помогут.
> и опасно.
Ружья куда опаснее. Но ими ведь пользуются после специальной для этого подготовки.
-
> Dimka Maslov © (26.05.16 11:52) [76]
> Вот тут уже никакие goto точно не помогут.
goto поможет всегда.
> Ружья куда опаснее. Но ими ведь пользуются после > специальной для этого подготовки.
И время от времени успешно стреляют себе в ногу.
-
> Юрий Зотов © (26.05.16 11:50) [75]
Ну вот не вижу я ничего удобного и безопасного в этом.
Написали код:
#func check(i, j, n) #if (i == 2) & (j == 2) then break(n) #endfunc
#for i = 1 to 5 #for j = 1 to 5 #check(i, j, 2) #next #next
Прошло два года. Понадобилось после окончания внутреннего цикла выполнить некоторые действия. Находим это:
#for i = 1 to 5 #for j = 1 to 5 #check(i, j, 2) #next #next
Изменяем вот так:
#for i = 1 to 5 #for j = 1 to 5 #check(i, j, 2) #next #Какой-то новый код #next
Запускаем, и... Работает неправильно. Почему???
И с goto точно такая же ситуация.
Чтобы на такие грабли не наступить, достаточно не использовать такие операторы.
Ясен пень, это все мое скромное мнение. :)
-
> goto поможет всегда.
for i := 1 to 10 do begin L: for j := 1 to 10 do begin for k := 1 to 10 do begin if k = 5 then goto L; end; DoSomething1; end; DoSomething2; end;
Изменится ли значение i после перехода на метку L, если внутри цикла k мы захотим прервать и его, и цикл j и чтобы DoSomethingи не выполнялись? Тут вообще полный этот как его произойдёт. А будь тут всего лишь Continue(3) - всё прекрасно будет.
> И время от времени успешно стреляют себе в ногу.
А это от недостатка подготовки. Мощными, но опасными предметами могут пользоваться только профессионалы, а не кто ни попадя
|