Конференция "Прочее" » Как вы относитесь к использованию меток в Delphi?
 
  • Kerk © (25.05.16 15:28) [60]

    > а FixInsight по этому поводу что-то ищет/предупреждает ?

    Нет. Надо будет добавить :)
  • DVM © (25.05.16 15:33) [61]

    > Kerk ©   (25.05.16 15:28) [60]


    > Нет. Надо будет добавить :)

    Использование GOTO не ошибка, не о чем тут предупреждать.
    Не, ну можно, конечно, в предупреждении выводить "Ошибка #100500 Не совпадение с мнением Kerka-а насчет идеального кода" :)
  • Юрий Зотов © (25.05.16 15:34) [62]
    > Внук ©   (25.05.16 15:14) [59]

    В Джаве есть:
    break метка
    continue метка

    По сути - те же goto. Причем сначала их не было, а в какой-то версии - появились. Значит, необходимость в них все же есть - и это тоже аргумент.
  • Kerk © (25.05.16 15:48) [63]

    > DVM ©   (25.05.16 15:33) [61]
    >
    > > Kerk ©   (25.05.16 15:28) [60]
    >
    > > Нет. Надо будет добавить :)
    >
    > Использование GOTO не ошибка, не о чем тут предупреждать.
    >
    > Не, ну можно, конечно, в предупреждении выводить "Ошибка
    > #100500 Не совпадение с мнением Kerka-а насчет идеального
    > кода" :)

    Так в этом же вся суть проекта! :)

    Если серьезно, то кроме потенциальных ошибок там еще есть реагирование на стилевые особенности кода. Слишком длинные методы, слишком большое количество переменных, вложенные with и т.п. Goto хороший кандидат туда же. Тем более что любую проверку можно легко отключить.
  • Внук © (25.05.16 15:58) [64]

    > Юрий Зотов ©   (25.05.16 15:34) [62]

    Так я про это написал в [45]. Операторы прерывания циклов с метками убили смысл goto совсем. Там, где они поддерживаются, конечно.
  • Eraser © (25.05.16 17:17) [65]
    вот такой код
    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, как кажется.
  • Германн © (26.05.16 01:27) [66]
    Попробую суммировать все высказывания со своей колокольни. Goto сам по себе ничем не вреден. Он всего лишь инструмент, которым надо уметь пользоваться. Если им пользуется тот кто умеет, инструмент может иногда помочь сделать код более удобным/более читаемым/более понятным. Если им пользуются троешники, то там "как повезёт".
  • Kerk © (26.05.16 02:06) [67]

    > Германн ©   (26.05.16 01:27) [66]

    Ну вот к чему это переливание из пустого в порожнее? Ты реально думаешь, что кто-то из присутствующих в этой ветке, в том числе те, кто против использования goto, не умеют им пользоваться? В плоскости умеет/не умеет тут вопрос даже не стоит.
  • Inovet © (26.05.16 03:49) [68]
    А почему никто не сказал, что на метку можно перейти из множества мест? Или в Делфи это не так?
  • Dimka Maslov © (26.05.16 09:31) [69]

    > Операторы break и continue ведь тоже частные случаи goto


    А если бы при помощи операторов break и continue догадались дать возможность прервать несколько циклов за раз, им бы цены не было. Но ведь мир далеко не идеален и для прерывания нескольких циклов нормальной простой и понятной альтернативы goto нет. Исключения, замыкания, анонимные методы - не панацея, лучше и проще они не сделают никогда. А вот написать Break(2) - как было бы классно. В моём собственном скриптовом языке такое реализовано и метки действительно стали вообще не нужны.
  • Владислав © (26.05.16 09:39) [70]
    Dimka Maslov ©   (26.05.16 09:31) [69]

    "А вот написать Break(2) - как было бы классно"

    На мой взгляд, это намного хуже goto. Возможностей меньше, а побочные явления в циклах те же.
  • Dimka Maslov © (26.05.16 11:03) [71]

    > Владислав ©   (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 для нескольких циклов возможностей меньше.
  • Владислав © (26.05.16 11:23) [72]
    > 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
  • Юрий Зотов © (26.05.16 11:35) [73]
    > Давайте попробуем повторить такое же в 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: ...
  • Юрий Зотов © (26.05.16 11:45) [74]
    > Dimka Maslov ©   (26.05.16 11:03) [71]

    И, кстати, Ваш подход, когда "уровень возврата" (двойка) зашит в тело самой функции, чреват ошибками. Стоит лишь вызвать ее из места, где уровень вложенности другой (не двойка). Поэтому программер, вызывая функцию, должен всегда это контролировать, а еще должен знать код функции. Все это и неудобно, и опасно.
  • Юрий Зотов © (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

  • Dimka Maslov © (26.05.16 11:52) [76]

    > А так будет работать?


    Будет. На уровне интерпретатора это реализовано через исключение.


    > Юрий Зотов ©   (26.05.16 11:45) [74]


    Это просто пример. Обычно, всё же до таких вещей не надо доходить. Достаточно и просто прерывать не сколько циклов. А ещё бывает удобно вложенный цикл прервать, а у внешнего сразу начать новую итерацию, т.е. иметь возможность ещё continue(n) использовать. Вот тут уже никакие goto точно не помогут.


    > и опасно.


    Ружья куда опаснее. Но ими ведь пользуются после специальной для этого подготовки.
  • Юрий Зотов © (26.05.16 12:00) [77]
    > Dimka Maslov ©   (26.05.16 11:52) [76]

    > Вот тут уже никакие goto точно не помогут.


    goto поможет всегда.

    > Ружья куда опаснее. Но ими ведь пользуются после
    > специальной для этого подготовки.


    И время от времени успешно стреляют себе в ногу.
  • Владислав © (26.05.16 12:09) [78]
    > Юрий Зотов ©   (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 точно такая же ситуация.

    Чтобы на такие грабли не наступить, достаточно не использовать такие операторы.

    Ясен пень, это все мое скромное мнение. :)
  • Dimka Maslov © (26.05.16 12:16) [79]

    > 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) - всё прекрасно будет.


    > И время от времени успешно стреляют себе в ногу.


    А это от недостатка подготовки. Мощными, но опасными предметами могут пользоваться только профессионалы, а не кто ни попадя
 
Конференция "Прочее" » Как вы относитесь к использованию меток в Delphi?
Есть новые Нет новых   [134432   +19][b:0.001][p:0.002]