Страницы: 1 2 3 След.
RSS
О вредном GoTo
 
Когда-то, когда макросы были страшные, "GO-TO!!!" звучало как глас из Мордора, макросописцев считал чародеями ), оператор обсуждался то ли в отдельной теме, то ли параллельно с другим вопросом...
Противники, готовьте помидоры (все равно не долетят, разобьются о личное_мнение).

Цитата из темы основного форума:
Цитата
Irregular Expression написал: существуют тонны написанных книг о вреде GoTo
... и относятся они в большей степени к языкам более высокого уровня.
Догмы - они тоже вредны бывают. Тем, у кого "Windows маздай", "GoTo отстой", "Наша Галя круче всех" и проч., без рассуждений и доводов, лучше проходить мимо. Принимается только трезвый взгляд на жизнь (под небольшим градусом тоже допускается :)).

Негатив от безусловного перехода какой? Правильно, нарушается структура, можно потерять нить... Но! Справедливо это для больших процедур, длинных листингов. В макросах, в которых в видимой части экрана наблюдаем и выход, и строку перехода, большой беды от GoTo нет. Или в кодах, где заведомо известно, куда нас понесет (например, к выходу из процедуры).
Второй минус  использования безусловного перехода - человек привыкает его использовать. А это может быть большим препятствием для работы с более продвинутыми язуками (не уверен, только логический вывод из собственных размышлений)

Бесспорно, выходить из одиночного цикла лучше по Exit For.
Кстати, прямо при написании возникла интересная мысль: Exit For по факту - тот же же безусловный переход, но четко привязанный к месту применения и к строке перехода. Из той же песочницы прочие Exit'ы. Получается, что все они - операторы безусловного перехода!
И книжки пишут, и опытные товарищи советуют вложенные циклы применять по минимуму - медленно работают. Но не всегда (даже очень часто) не получается следовать этому правилу. Выходить наружу из внутреннего цикла можно по флагу, но это дополнительная проверка (если три цикла - две проверки). Гораздо удобнее сказать: а пошел бы ты на GoTo :)

Сам не сторонник применения GoTo, но и отказываться от него в VBA не стоит. Это как с летучими функциями листа: если есть замена не хуже, то всякие СМЕЩ, ДВССЫЛ применять не нужно. Но ведь есть случаи, когда без них не обойтись или замена будет хуже.

Использую безусловный переход в двух случаях (больше с ходу не вспомнил):
1. В начале процедуры для выхода из нее при проверках . Т.е. всегда понятно, что GoTo - это завершение и переход следует искать недалеко от End Sub.Да и зачем искать, если понятно? :) Нет, не замена Exit Sub.
Например, нужно открыть другой файл. Отключаем сообщения, обновление экрана, открываем книгу... и тут проверки на наличие листа, корректность данных, поиск таблицы и проч. Просто Exit Sub не получится - нужно включить отключенное. Наставить каскад If - код разрастается и становится менее читабельным. GoTo здорово помогает.
2. В этих самых циклах. Здесь использую очень редко. Тоже применяю флаги или разделение циклов. Но иногда бывает. Если точка перехода - вот она, рядом, и любой другой пользователь увидит ее без напряга. А еще комментарий подвесить и имя понятное дать...

Ага, вспомнил еще одну "штучку" - обработчик ошибок (вообще, его бы тоже пореже задействовать). Куда-то же люди переходят: On Error GoTo.... И это советует кто? Разработчик! (если бы не советовал, придумал бы другой флаг).

Так что книги читать очень полезно, но и думать не запрещается )
 
Не имею глубоких познаний в данном конкретном вопросе. Однако, если инструмент создан и существует, значит есть ситуации в которых его применение уместно и избавляет от лишних танцев с бубном.  :)  
 
Доброе время суток.
Кидаться не буду. Помидоры до Москвы то не довезли, а уж к вам точно не попали :)
Цитата
vikttur написал:
Но не всегда (даже очень часто) не получается следовать этому правилу.
Может вы используете не алгоритмы и структуры данных? Понятно, что сортировка пузырьком пишется даже спросонья, но быстрее то будет quick sort?
А так. Даже в Java, в которой гордо отказались от goto, тем не менее есть конструкция вида break метка  :D
 
Лично я использую GoTo и наплевать чего говорят другие. Чаще всего использую в тех случаях, когда можно избежать написание дополнительного кода. Я не говорю про выходы из циклов, с этим всё понятно что есть методы выхода и если написать дополнительные проверки на If End if, но это опять же усложняет код, особенно когда он большой, и с этими всеми вложениями в конструкциях логических можно запутаться легко. Вот например когда использование GoTo вполне разумно и когда требуешь от пользователя ввести что-то:
Код
Sub Пример()
KLM:
a = InputBox("Введите число")
If IsNumeric(a) Then
    'Дальнейшая обработка
Else
    GoTo KLM
End If
End Sub
Без использования такой структуры пришлось бы воротить лишнего, а тут всё красиво и ни чуть не переломился ни я ни Excel.
И если честно я вообще не понимаю откуда эти ноги выросли, что GoTo это вредно. Команда есть, значит использовать её можно. Можно решить и всякими циклами вопрос, но есть коды где даже и циклов нет, и вот там опять очень удобно перебрасывать пользователя. Можно заменять функциями и прочим, но лично я вообще редко применяю функции, так как легко потеряться в макросе.
Мастерство программиста не в том, чтобы писать программы, работающие без ошибок.
А в том, чтобы писать программы, работающие при любом количестве ошибок.
 
Цитата
Alemox написал:
а тут всё красиво
По вашему - это уродливо :qstn:  :excl:
Код
Sub Пример()
Dim a
Do
    a = InputBox("Введите число")
Loop Until IsNumeric(a)
'Дальнейшая обработка
End Sub
 
vikttur, если приводите цитату, приводите целиком. Мой посыл был  не в том, что GoTo использовать нельзя, а в том, что его существование - это тема научного холивара, который начался до лично моего рождения и продолжается (хоть и с почти угасшим энтузиазмом) по сей день. Больная тема, в общем, т.к. ни противники не доказали безусловный вред безусловного перехода, ни сторонники не смогли привести ни одного 100%-го случая, когда переход по метке необходим и его нельзя заменить другими конструкциями языка.
Цитата
... и относятся они в большей степени к языкам более высокого уровня.
Догмы - они тоже вредны бывают. Тем, у кого "Windows маздай", "GoTo отстой", "Наша Галя круче всех" и проч., без рассуждений и доводов, лучше проходить мимо. Принимается только трезвый взгляд на жизнь (под небольшим градусом тоже допускается ).
А вот и не соглашусь. С какого перепугу VBA оказался в языках низкого уровня %)? Кроме того, запутать беспорядочными метками код маленькой процедуры, умещающейся на экране, вполне реально :).
Цитата
Кстати, прямо при написании возникла интересная мысль: Exit For по факту - тот же же безусловный переход, но четко привязанный к месту применения и к строке перехода. Из той же песочницы прочие Exit'ы. Получается, что все они - операторы безусловного перехода!
Нет. Это операторы выхода, а не перехода по метке. Это принципиально, т.к. место выхода известно, а по метке нас может бросить  в любое место в рамках процедуры/функции.
Цитата
Выходить наружу из внутреннего цикла можно по флагу, но это дополнительная проверка (если три цикла - две проверки). Гораздо удобнее сказать: а пошел бы ты на GoTo
Так никто не препятствует, в т.ч. и я. В той теме, откуда Вы выдрали мою цитату, у ТС компилятор "ругался на выход по GoTo", и я ему предложил альтернативную, пусть и менее удобную конструкцию, чтобы это проверить. Только и всего.
Цитата
1. В начале процедуры для выхода из нее при проверках . Т.е. всегда понятно, что GoTo - это завершение и переход следует искать недалеко от End Sub.Да и зачем искать, если понятно? Нет, не замена Exit Sub.
Лично встречал на этом форуме много раз, как люди имитируют циклы с помощью конструкций label: If - Else GoTo label. После такого стресса мне уже никогда не будет понятно, что GoTo - это завершение и что метку перехода надо искать в конце.
Цитата
Например, нужно открыть другой файл. Отключаем сообщения, обновление экрана, открываем книгу... и тут проверки на наличие листа, корректность данных, поиск таблицы и проч. Просто Exit Sub не получится - нужно включить отключенное. Наставить каскад If - код разрастается и становится менее читабельным. GoTo здорово помогает.
Альтернатива: выделение такого кода в отдельную процедуру, VBA - ООП язык, хоть об этом часто и забывают те, кто пишет макросы. Кстати, гораздо удобнее, на мой взгляд.
Цитата
Ага, вспомнил еще одну "штучку" - обработчик ошибок (вообще, его бы тоже пореже задействовать). Куда-то же люди переходят: On Error GoTo.... И это советует кто? Разработчик! (если бы не советовал, придумал бы другой флаг).
Тот самый разработчик, который так давно не обновляет VBA и раз за разом грозится исключить язык из пакета. Тот самый разработчик, который в  последних релизах обновляемого VB настоятельно рекомендует не пользоваться "устаревшим и небезопасным" On Error GoTo :)... Тот самый разработчик, который даже очевидные коллизии между IsDate и CDate исправить/заметить не в состоянии и рекомендует их использовать вместе, в результате чего у программистов разрыв шаблона и ошибка компиляции при малейшей опечатке... Думаю, Вы лучше меня можете продолжить этот перечень причин c разумным подозрением относиться к тому, что этот разработчик пишет о нелюбимом им VBA :).
Изменено: Irregular Expression - 24.11.2017 09:07:43
 
Андрей VG, это не уродливо, а вполне применимо. Я говорю про то, что если дать задание написать какую-то программу разным программистам. То они все её напишут. И даже если внешне она будет абсолютно идентична, то если заглянуть внутрь, то там можно увидеть, что коды совершенно разные, так как каждый человек видит по своему шаги к достижению цели. На выходе одно, а алгоритмы разные.
Мастерство программиста не в том, чтобы писать программы, работающие без ошибок.
А в том, чтобы писать программы, работающие при любом количестве ошибок.
 
Цитата
Alemox написал:
что коды совершенно разные
Кто бы с этим спорил. Но вы уклоняетесь от темы обсуждения. Процитирую коллегу
Цитата
Irregular Expression написал:
Лично встречал на этом форуме много раз, как люди имитируют циклы с помощью конструкций label: If - Else GoTo label. После такого стресса мне уже никогда не будет понятно, что GoTo - это завершение и что метку перехода надо искать в конце.
Вопрос - зачем так писать цикл? От незнания языка? Или это стремление к минимализму - писать в стиле ассемблера (да, там только jump not zero, jump zero)?
Изменено: Андрей VG - 24.11.2017 09:20:36
 
Цитата
Irregular Expression: если приводите цитату, приводите целиком. Мой посыл был  не в том, что GoTo использовать нельзя
Цитата послужила поводом для обсуждения. В цитате - только факт о том, что много пишут о вреде GoTo. Никаких претензий к автору высказывания нет. Извините, ни на кого не хотел наезжать.

Цитата
С какого перепугу VBA оказался в языках низкого уровня %)?
Нет, я писал не о низком уровне VBA, но о более высоком уровне других языков.

Цитата
vikttur: Exit For... прочие Exit'ы. Получается, что все они - операторы безусловного перехода!
Цитата
Irregular Expression: Нет. Это операторы выхода, а не перехода по метке.
Конечно! Я ведь не утверждал, что это родные братья GoTo. Но
Цитата
vikttur: по факту - тот же же безусловный переход, но четко привязанный к месту применения и к строке перехода
Разные инструменты, конечно. Но сам смысл - похож. Именно об этом писал. Название другое, возможно, внутренняя реализация не такая, но для пользователя суть похожа. И оператор выхода, и оператор безусловного перехода дают команду перейти к указанному месту кода и никуда иначе.
Отметил похожесть, но не одинаковость.

Цитата
Irregular Expression: Кроме того, запутать беспорядочными метками код маленькой процедуры, умещающейся на экране, вполне реально
также реально запутать наличием десятков флагов, отсутствием отступов, названиями переменных :) Ну, везде же голова нужна!
Писал не о бездумном применении 25 переходов на один квадратный сантиметр. Выходим отсюда вон туда. Все.

Цитата
vikttur: всегда понятно, что GoTo - это завершение и переход следует искать недалеко от End Sub
И это тоже - не о тех квадратных сантиметрах. Если в коде GoTo применяется только для выхода, только в начальных проверках и это четко ясно (например, тот же комментарий перед процедурой), то почему бы нет?

И этот частный пример, и об обработчике ошибок... В общем, главный посыл всей этой писанины:
"а почему бы не применять GoTo в VBA" вместо "убить его и зарыть поглубже".
Для "зарыть" пока не вижу веских аргументов.
 
Цитата
Андрей VG: Может вы используете не алгоритмы и структуры данных?
Да, возможно.
Код
For i = 1 To 100
      For j = 1 To 100
            a(i, j) ......
      Next j
Next i

Не всегда вижу, как такую конструкцию заменить на код без вложенных циклов и как при необходимости выйти из внутреннего цикла за Next i, не применяя флаги или GoTo. Возможно, не дорос. Года два тому было и по 6-7 вложенных циклов :). Сейчас вижу, что глупостями занимался ) (но, кстати, для тенировки мозгов очень даже полезно)
 
Исторически так сложилось, что Бейсик создан сразу после ассемблера, где оператор Goto через байт  ;)  - смиритесь. Хотя вот мне непонятно, что было так трудно добавить команду Continue в цикл для перехода в начало. Бесит прям.   :evil:  
Excel + SQL = Activetables
 
Тонны бумаги и гагабайты hdd остались на полях бескомпромиссных , лютых боёв сторонников и противников... Но нет, жив ещё go to, помнят о нем ярые противники и преданные сторонники, да и просто нейтральный процент (в т.ч. я :) ) спецов.
«Бритва Оккама» или «Принцип Калашникова»?
 
PowerBoy, в VB есть Continue For, но синтаксис VB в реализации VBA перестал обновляться до появления этой команды.
Кстати, это ещё один (помимо названных vikttur) случай, когда в VBA использование GoTo может быть оправданным: в единичном случае Continue превосходно заменятся If-Then (пропускаемый код до конца цикла) End If, но когда таких пропусков нужно много, If-ы приходится вкладывать друг в друга, и они разрастаются в жуткое "дерево", тогда как с GoTo можно повысить читаемость кода, заменив многочисленные End If End If End If End If на одну метку.
 
Если по теме, думаю, дело не в go to, а в руках, а точнее в голове. Можно и без go to "наговнокодить" так, что потом и сам не разберешь. Достойный кандидат - on error resume next, да тысячи их.   Код должен быть красив, лаконичен, эффективен. Но красота у каждого своя)
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
Irregular Expression написал:
Больная тема
Не вижу никакой боли: кто хочет - использует, кого тошнит от этой конструкции - не использует ))
Вообще не вижу предмета для спора. А эти "не комильфо", "не кошерно", и прочее - надуманное, как мне кажется.
 
Я не сторонник GoTo. Если говорить про ассемблер, то это вообще сплошной GoTo. Вот, например, простейший цикл, который  к переменной x прибавляет по единичке до 20. Как видно, в ассемблере переходы завязаны именно на метках:
Код
       mov eax, 10
       mov ecx, 20
loop1: inc eax
       cmp eax, ecx
       jle loop1
       dec eax
Как видно, инструкци jle (jump if less or equal) и выполняет тот самый безусловный переход. На VBA это выглядит более читабельно:
Код
Dim x As Integer
Const y As Integer = 20
x = 10
While x <= y
    x = x + 1
Wend
Да, теперь наш код читабелен и удобоварим. Согласен с котярой, что использование GoTo - дело, конечно, личное. Но вопрос в другом - почему этот оператор до сих пор существует? В исходных кодах библиотек платформы .NET Framework - 1583 строчки, где используется GoTo (см. файл)!!! Однажды я видел код.... Этот оператор использовался везде - и даже циклы были написаны в стиле а-ля ассемблер:
Код
Dim x As Integer

LOOP1:
x = x + 1
If x < 10 Then GoTo LOOP1
Ну и в таком духе. Интересно, а как бы vikktur или Alemox написали цикл тройной вложенности через GoTo?
Код
Dim x, y, z
While x < 10
    x = x + 1
    While y <= x * 2
        y = y + 10
        While z <= y * 2
        Wend
    Wend
Wend
Изменено: SuperCat - 26.11.2017 22:29:10 (Добавлен файл)
There is no knowledge that is not power
 
1. Я тоже не сторонник GoTo. Но и не противник
Цитата
bedvit написал: нейтральный процент

Цитата
LOOP1: x = x + 1
If x < 10 Then GoTo LOOP1
2. "не моя метода" (см. п.1 - не сторонник) )

Цитата
а как бы vikktur или Alemox написали цикл тройной вложенности через GoTo?...
3. Tак, как в сообщении выше (см. цикл тройной вложенности), я бы тоже не писал. Зацикливание по z :)
Без флагов вот так можно  (см. п.1 - не противник):
Код
Sub jjj()
Dim x, y, z, k
    While x < 10
        x = x + 1
        
        While y <= x * 2
            y = y + 10
            
            While z <= y * 2
                k = k + 1
                If k = 123 Then GoTo ext_ ' уходим из каскада
            Wend
        Wend
    Wend
    
ext_:
    If k = 123 Then Debug.Print x + y
End Sub

Какие еще варианты выхода (флаги не применяем!)?

Попутно: как правильно в данном случае: вложенность тройная или двойная? Вложений-то два: y, z?
 
Виктор, схитрил ты, однако! Тройной цикл БЕЗ While и Do...Loop! :) Вот такую жесть я приблизительно видел)
Но, конечно, не будем спорить, нужен он или нет.
Раз он есть - значит, есть ему применение (просто в VBA на нём построен отлов ошибок), но оно должно быть разумным и оправданным.
There is no knowledge that is not power
 
Цитата
SuperCat написал: схитрил ты, однако! Тройной цикл БЕЗ While и Do...Loop!
Да понял я, о чем был вопрос. Но заменять операторы циклов не стоит. А в ответ на колкость отправил свою иголку (о зацикливании) :)

А вообще: есть ли решение выхода из внутреннего цикла? GoTo  и флаги - понятно. Что еще можно?
 
SuperCat, познавательно! Спасибо.
Цитата
vikttur написал:
выхода из внутреннего цикла
видится циклы с условиями Do... Loop...
Жаль, что нельзя, к примеру, так :)
Код
For a = 1 To 50
    For b = 1 To 50
        If a = 2 Then exit for a 
    Next b
Next a
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
vikttur написал: Что еще можно?
Думаю пока MS не решат дополнить VB в офисе, то ничем. Вообще не вижу вреда использования GoTo. Кому интересно почитайте статейку.
Мастерство программиста не в том, чтобы писать программы, работающие без ошибок.
А в том, чтобы писать программы, работающие при любом количестве ошибок.
 
Видел когда-то эту статейку.
Цитата
Alemox написал:  я использую GoTo и наплевать чего говорят другие.
Там, кстати, есть и о бездумном применении оператора. Не всегда нужно "наплевать"...

Цитата
bedvit написал: видится циклы с условиями Do... Loop...
Я не вижу... Как из цикла первого уровня увидеть изменения в последнем вложенном цикле? Ведь там что-то меняется и первый цикл сможет что-то проверить только после окончания обработки в предыдущих циклах...
Можно на примере?
 
Как то так (пишу с тел., идея такая):
Код
Do While c<10 and a<5
    a=a+1
    Do While c<10 and b<5
       b=b+1
       c=a*b   
    Loop
Loop
Изменено: bedvit - 27.11.2017 20:41:36
«Бритва Оккама» или «Принцип Калашникова»?
 
Вместо "с" может быть любой признак, к завершению циклов. Булево значение, текст или число.

Виктор, что скажете? Другой вопрос, мне как чел. уважающему оптимизацию, представляется, что вариант с go to  работает быстрее, чем доп.проверка в циклах.
Изменено: bedvit - 27.11.2017 21:17:56
«Бритва Оккама» или «Принцип Калашникова»?
 
В этом коде внешний цикл все равно прокручивается вхолостую. Но это же пример и условия можно подогнать...
По факту - тот же флаг, но спрятанный в условиях. Т.е. в циклы все равно возвращаться.
Не думаю, что применимо во всех случаях, но за идею спасибо. И, да - GoTo выкинет сразу, без проверок
 
Верно, тот же флаг по факту. Да пример "на коленке" в автобусе писал, вот так по-моему более точно передает мысль:
Код
Do While c < 10 And a < 5
    a = a + 1
    c = a * b
    Do While c < 10 And b < 5
       b = b + 1
       c = a * b
    Loop
Loop
или так
Код
Do While a * b < 10 And a < 5
    a = a + 1
    Do While a * b < 10 And b < 5
       b = b + 1
    Loop
Loop

Не являюсь ярым борцом с go to, поэтому в отдельных случаях, когда это применимо, раз или два в коде могу использовать. Правда редко. Последний раз по-моему здесь(на нашем форуме). Можно обойтись было и без go to, но код выходил в 2 раза длиннее и хуже читаемый (в то время я так думал :) ).
«Бритва Оккама» или «Принцип Калашникова»?
 
Код
for i=1to 5
      If Instr(...) then goto 0. ; Мне не нужно выходить EXIT FOR, мне нужно перейти на новый i+1 уровень.
0:
next
------------
Пока я эту проблему не решил, использую.
???
"..Сладку ягоду рвали вместе, горьку ягоду я одна."
 
Если правильно понял:
Код
Sub Test()
Dim i As Long
    For i = 1 To 10
        Debug.Print i
        If i = 3 Then i = i + 1
    Next
End Sub
 
В некоторых ситуациях GoTo очень даже кстати: например, пользователю предлагается ввести в InputBox некое значение. А при ошибочном вводе нужно дать ему возможность повторить попытку - вот тут GoTo и пригодится )
 
Не борюсь ни за, ни против Go To. Однако, признаюсь, что последний раз применял Go To  ещё на ZX-Spectrum (и последний раз она выглядела, как JP или JR - ассемблер Z80).
Потребности непосредственно в Go To у меня не возникает, хотя часто применяю Exit (For, Do, Sub...). Так же замечаю, что для меня разобраться в работе программы, где часто применяют Go To сложнее, чем без оного (а если ещё и структура не поддерживается...  :( :excl: )
Кстати, по выходу из цикла через Go To. Компилирующие языки могут реализовывать циклы, храня на стеке счётчик цикла, поэтому "выпрыг" из каскада циклов, сделанный по привычке, может однажды стать ошибкой (пусть не в VBA, а в каком-то другом языке).
Страницы: 1 2 3 След.
Наверх