Xpoint
   [напомнить пароль]

В PHP ввели goto

Метки: [без меток]
2009-05-14 16:36:28 [обр] Даниил Иванов(0/63)[досье]

http://ru2.php.net/manual/ru/control-structures.goto.php
The goto operator is available since PHP 5.3.

А зачем, как вы думаете?

спустя 39 минут [обр] Thirteensmay(17/157)[досье]

Фигасе ! его там небыло ?

Ну imho за тем что хоть и в крайне редких случаях, но оператор полезный. Видать наконец таки дошло, или скорее просто время появилось реализовать сию не первоочередную фичу ;)

спустя 7 часов [обр] Сергей Сирик(180/737)[досье]
Кто-то из программеров неправильной травы курнул и решил приколоться?
спустя 50 минут [обр] Юрий Насретдинов aka yUAC(6/7)[досье]

К примеру:

function do_some_processing()
{
$fp1 = fopen(...);
$fp2 = fopen(...);
$fp3 = fopen(...);

...

if(!some_action()) goto close_all_and_return_false;

...

if(!some_other_action()) goto close_all_and_return_false;

...

return true;

// сюда никак, кроме как с помощью goto не добраться

close_all_and_return_false:

fclose($fp1);
fclose($fp2);
fclose($fp3);

return false;

}

Если у Вас в функции нужно закрывать какие-нибудь ресурсы или делать другую «очистку», то перед тем, как вернуть сообщение об ошибке, нужно закрыть эти ресурсы. Если нет goto, то нужно изворачиваться и, к примеру, закрывать все ресурсы в каждом из if'ов, то есть, по сути, пользоваться copy-paste. В этом случае использование goto более предпочитетельно.

спустя 5 часов [обр] Алексей Полушин(62/231)[досье]
Юрий Насретдинов aka yUAC[досье]
Ваш пример легко обходится без goto:
function do_some_processing()
{
$fp1 = fopen(...);
$fp2 = fopen(...);
$fp3 = fopen(...);
...
do {
if(!some_action()) break;
...

if(!some_other_action()) break;

...

return true;

} while(0);

fclose($fp1);
fclose($fp2);
fclose($fp3);

return false;

}
спустя 2 часа 35 минут [обр] Thirteensmay(17/157)[досье]

Сергей Сирик[досье] Вот и скажите кто из выше представленных двух курнул неправильной травы ? Тот кто сделал максимально эффективно, без лишних операторов и логично, или тот который прилепил цикл который а) лишний потому что впринципе тут не нужен б) сбивает с толку, причем тут вообще цикл в) просто является костылем.

Алексей Полушин[досье] Ключевое слово обходится ;) Зачем обходить если можно сделать прямо ? Если уж вы и пытаетесь рассказать что добавление лишних операторов это хорошо, то тогда хотябы сделайте это логично, тут более уместны исключения, но избыточности это всеравно не отменяет.

В любом случае примеры эффективности goto вышеприведенным не ограничиваются. Наиболее показательна ситуация с циклами глубокой вложенности когда допустим из 5-ой итерации надо выйти на вторую а из четвертой на первую. Что предлагаете делать в этом случае ? Обрабатывать флаги и бряки на каждой итерации ? А с goto это делается элементарно. Таже ситуация имеет место не только во вложенных циклах но и в сложных вложенных условных конструкциях.

спустя 1 час 53 минуты [обр] Алексей Полушин(62/231)[досье]
Ну это нормальный финт в языках где нету goto. Кстати выход из вложеного цикла в php делается элементарно - у break есть параметр :)
спустя 1 час 5 минут [обр] Thirteensmay(17/157)[досье]

Вот и я про то же, в языках где нету goto приходится "финтить". То что у break есть параметр - хорошо, прикрутили очередной костылик, но что если нам надо выйти не к началу блока/итерации а чуть позже, пропустить например некоторую инициализацию в начале ? break с меткой как в жабе ? цивилизованная форма goto ;) ? уроды блин.

Вообще я уписываюсь с ситуации, для обхода goto придумано столько костылей, а что в результате ? либо всеравно не гибко, либо бардак еще похлеще чем с goto. Хватит тупо обезьянничать что goto это зло, не зло вовсе, а вполне нормальный полезный оператор, другое дело что как и любым другим им надо правильно уметь пользоваться. Корешки то у нас тут откуда ростут ? Из низкоуровневых языков, там без goto жизни нет, вот авторы высокоуровневых и решили, а зачем нам goto, это низкоуровневый, тяжелый подход, а у нас то высокоуровневый - заклеймим goto, достаточно структурных ифов, а то вся наша оптимизация прахом пойдет. Ну и отказались по началу, по крайней мере жестко это распиарили, вот только практика потом показала что есть несколько моментов где goto весьма полезен и не нарушает оптимизации, только область применения сокращается - нельзя скакать по коду как хочешь так как это при низкоуровневом подходе, теперь надо думать куда и как скачешь. Поэтому практически во всех языках goto есть, а в тех что нет - добавляют ;) А что касается повсеместного воя что goto это зло - так оно понятно, тут есть 2 момента, вопервых тупое бездумное обезьянство, а во вторых дело в том что правильно пользоваться goto надо уметь, нужен некоторый опыт, у начинающих программистов его нет, поэтому в подавляющей массе учебной литературы goto гнобят, и правильно, а то начинающие такое начинают c goto воротить что не в сказке сказать. А вот по мере накопления опыта goto может быть полезен. Обезьянничать только не надо.

спустя 2 дня 8 часов [обр] Даниэль Алиевский(5/125)[досье]

Thirteensmay[досье] Уважаемый Thirteensmay, уважьте хотя бы мой опыт. Я программирую на Java около 10 лет, только что разработал сложнейшую библиотеку, намеки на которую можно найти на моем сайте algart.net, но до сих пор ни разу не пострадал из-за отсутствия goto в Java. Выход из блока любого уровня вложенности и освобождение ненужных ресурсов прекрасно решаются метками у блоков и оператором finally.

Пожалуй, был все-таки один случай, когда я переводил программу с Паскаля (и более поздней версии на C++) и мне пришлось задуматься, чем заменить goto. Это был автомат для обхода периметра двумерной частицы, "нарисованной" на битовой матрице. Этот автомат может находиться в одном из 4 состояний, соответствующих сторонам квадрата 1x1, которую в данный момент автомат "обходит". На Паскале/С++ эта задача решалась через goto: в зависимости от ситуации (с соседними квадратами 1x1) производился переход (goto) в одно из 4 возможных состояний. Но для Java такое решение и коряво, и неэффективно. Вместо псевдобесконечного цикла с goto у меня появился объект Mover, который производил переход к следующему отрезку периметра и для которого существовало 4 реализации. Алгоритм в итоге получился очевиднее, легче оптимизируемым (эти 4 реализации можно было подставить разные для разных реализаций битовых матриц) и, что интересно, эффективнее прежней реализации на C++.

Во всех остальных случаях, которые в случае последних моих библиотек составили 8 мегабайтов java-файлов, про goto мне даже не пришлось вспоминать. Вот про var-параметры, которых в Java тоже нет (примитивные типы, передаваемые по ссылке) вспоминать приходилось, правда, очень редко. Про goto - нет.

спустя 13 часов [обр] Thirteensmay(17/157)[досье]
Даниэль Алиевский[досье] Давайте уважать друг друга, Вы не будете отбирать у меня goto, а я не буду говорить то что в таких случаях положено. Я не утверждаю что goto необходимый оператор, а лишь то что в редких случаях полезный. То что в яве есть break с меткой весьма умиляет, скажите что это по сути ? Как я уже говорил таже ситуация имеет место не только во вложенных циклах, но и в сложных вложенных условных конструкциях. Да, теоретически такие нагромождения следует переписывать, но на практике это не всегда возможно, ввиду отсутствия времени и т.п., тут goto также может быть полезен, да это криво, но это реально очень существенно экономит время, а частенько и вообще просто позволяет решить задачу (в установленные рамки, ибо в др. ее смысл теряется). Похоже PHP'шники просто не церемонясь решили проблему в принципе.
спустя 11 часов [обр] Даниэль Алиевский(5/125)[досье]

Thirteensmay[досье] Но тогда назовите, пожалуйста, ситуацию, в которой действительно нужен именно goto - а не те, как вы говорите, "костыли", которые его заменяют. Подобные выходу из помеченного блока. Я попытался назвать подобную ситуацию - но в рамках Java она лучше решается иными путями. (Благодаря таблицам указателей на методы, которые подразумеваются всякой реализацией полиморфизма.) В рамках PHP, к сожалению, я некомпетентен и не могу утверждать или опровергать, что такая-то ситуация с помощью goto решается наилучшим образом - но вы можете, по крайней мере, обозначить эту ситуацию.

Разумеется, в условиях нехватки времени можно применить "впопыхах" любой оператор и даже воспользоваться прямыми ошибками разработчиков. Но это еще не означает, что эта "фича" действительно в среднем способна сэкономить время. Мне доводилось применять предельно кривые методы решения задач, но это не доказывает, что они нужны и полезны.

спустя 13 часов [обр] Thirteensmay(17/157)[досье]

Даниэль Алиевский[досье] Почитайте тему с начала, эти ситуации уже названы. В приведенном Алексей Полушин[досье] примере проще и логичнее сделать с помощью goto. Далее, в PHP у break нет метки, что если надо выйти не к началу/концу блока а чуть позже ? опять goto наиболее простой вариант если вообще не единственный. И по поводу экономии времени - да goto действительно способен экономить время а не передумывать и переписывать кусок кода полностью, несомненно это некрасиво, но когда реально припечет действительно помогает, странно что при вашем опыте вы не сталкивались с такими ситуациями, вот сейчас вокруг меня сидит 6 программистов, 2 из них (кроме меня) признают что сталкивались.

Вот еще кстати давеча наткнулся: http://ru.wikipedia.org/wiki/GOTO

Например, GOTO был намеренно полностью запрещён в Java и Ruby. Вместе с тем, в Аде — одном из наиболее продуманных с точки зрения архитектуры языке за всю историю[3], GOTO всё же был оставлен.

 Опять травокуры виноваты ? ;)

спустя 2 часа 52 минуты [обр] Thirteensmay(17/157)[досье]
Даниил, тут в общем то вопрос как известно довольно религиозный ;). Все упирается в то насколько мы готовы следовать принципам структурного программирования, и насколько хорошо они реализованы в конкретном языке. С одной стороны структуризация это конечно хорошо, но с др. это по сути ограничение, ужесточение. А ведь мы говорим о языках программирования общего назначения, они в большой степени стремятся к гибкости и универсальности. Получается противоречие, одни решают его путем введения дополнительных ограниченных конструкций, типа break с меткой, другие оставляют универсальные решения типа goto и указателей. Первые при этом достигают лучшей структуры но гдето чуть чуть теряют в универсальности, где то чуть в оптимальности. Вторые полностью сохраняют это но не добиваются улучшения структуры. Если же при этом посмотреть в чем заключается корень неструктурированности программы, то оказывается что не в языке в первую очередь, а в голове программиста. Я надеюсь вы согласитесь с тем что писать крупномасштабные, структурированные и понятные программы на Perl возможно, вместо Perl можно подставить множество языков имеющих goto, т.к. дело не в этом операторе. И наоборот, если бы скажем в Java имелся goto то его использование вместо break с меткой, нисколько бы не привело к ухудшению структуры. В результате нам остается ответить на вопрос что лучше, совсем слегка но жестко пожертвовать гибкостью в угоду слабенького улучшения структурированности, или ни чем не жертвуя предоставить этот выбор программисту в любой необходимый момент ?
спустя 3 часа 41 минуту [обр] Алексей Полушин(62/231)[досье]
А как вам такой вариант goto http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Labels-as-Values.html ?
спустя 16 часов [обр] Thirteensmay(17/157)[досье]
Смерть тараканам ! ;) Это кстати Даниилу на заметку, а то он делает Благодаря таблицам указателей на методы, которые подразумеваются всякой реализацией полиморфизма что Алексей Полушин[досье] приблизительно равно вашему варианту с циклом. Вообще многим то что я тут вещаю может показаться отходом от структурированности и съездом на более низкий уровень (я имею ввиду ЯП низкого/среднего/высокого уровня), так вот, бывает откроешь код какогонибудь ядреного сишника, и ужаснешся, потом поковыряешь, ан нет, все в высшей степени структурировано оказывается, просто понятия о структурированности, и самое главное средства ее реализации у разных людей весьма отличаются.
спустя 6 часов [обр] Даниэль Алиевский(5/125)[досье]

Я не знал, что в PHP нет break с меткой - как-то пока руки не дошли освоить этот язык. Конечно, ситуация, когда нужно выйти из некоторого сложного логического блока, закончив тем самым вычисления, встречается сплошь и рядом. Взять хотя бы двойные циклы по элементам матрицы. Оператор break с меткой блока решает именно эту задачу и не наносит никакого вреда. Более того, даже повышает логичность языка: ведь тогда и обычный break, и все стандартные циклы становятся просто сокращениями конструкции "помеченный бесконечный цикл" + "break из него в случае наступления условия". И почему в PHP не ввели такой оператор? В Perl я успешно пользовался такой возможностью.

А при наличии break с меткой, механизма исключений и традиционных виртуальных методов, повторюсь, я никак не могу найти пример конструкции, которая решается с помощью goto хоть в чем-то лучше. Например, проще или эффективнее. Приведите такой пример! Хоть один. Кроме разве что возможности специально запутать программу, при наличии такого желания.

И в религиозных спорах бывают аргументы. А тут я их, увы, вообще не вижу. Кроме несколько тенденциозного заявления о "продуманности Ады", которая, несмотря на продуманность, благополучно почила.

спустя 2 часа 39 минут [обр] Thirteensmay(17/157)[досье]
Даниэль Алиевский[досье] О ! ;) при наличии break с меткой, механизма исключений и... Значит необходимость break с меткой вы таки признали ;) Это хорошо, оно здесь является ключевым, причем работающего не только в контексте циклов, а вообще любых блоков. И теперь скажите мне чем в таком случае goto m1, отличается от break m1 ? Да ничем. В современных языках goto никак кроме как в контексте break с меткой, уже давно использовать не получится, как только вы попытаетесь полезть не туда вам компилятор по рукам даст или пр. инфраструкутра. Не везде конечно, про случаи типа представленного Алексей Полушин[досье] чуть выше умолчим, там басня вообще иная, а основной подход именно такой, goto ограничено, например в ObjectPascal и PL/SQL точно, на них сейчас пишу, гдето помнится еще натыкался. Так вот, давайте определимся мы про что ? Про старый C ? в котором бряки с меткой нет, и около которого основная критика goto когда то строилась, или про современное положение вещей, когда goto не первый десяток лет как ограничен, а народ все продолжает обезьянничать ?
спустя 11 часов [обр] Алексей Полушин(62/231)[досье]
В РНР есть break не с меткой, а с уровнем вложенности. Возможности те же, но менее удобно.
Thirteensmay[досье] Я не говорил, что вариант с фиктивным циклом лучше, чем с goto. Это было ответом на утверждение о том, что если нет goto, в описаной ситуации приходится пользоваться copy-paste кода. Есть и другие варианты - вложеные if к примеру. Вобщем, обойтись без goto можно, но и вреда от его существования нет. Нечитабельный код можно написать и без goto.
спустя 3 часа 35 минут [обр] Thirteensmay(17/157)[досье]
Согласен, разве что немного уточнить:
Вреда от goto при разумном его использовании нет, обойтись без него (break c меткой) можно, но это требует дополнительных усилий.
спустя 10 часов [обр] Даниэль Алиевский(5/125)[досье]

Thirteensmay[досье] Да, конечно, в необходимости break с меткой я никогда особо и не сомневался. Максимально общий вариант - любые блоки. О целесообразности такой общности можно спорить (все-таки пример Насретдинова явно подозрителен с точки зрения общей архитектуры), но то, что в принципе надо уметь выходить из циклов более чем однократной вложенности, кажется очевидным.

Но отличие break с меткой от goto мне кажется ничуть не меньшим, чем, скажем, отличие goto от вызова процедуры или Фортрана от Паскаля. Break с меткой - это органичная часть структурной логики, естественно дополняющая такие вещи, как досрочный выход из цикла или выход из процедуры. Это просто возможность покинуть блок, не дожидаясь его окончания; программа же остается иерархически структурированной: оператор - блок - процедура - класс или модуль, дальше зависит от языка. А goto - это возможность передавать управление в любую или почти любую точку кода, очень важный инструмент для ассемблера или просто старых языков типа Фортрана, позволяющий промоделировать любые более сложные конструкции, но совершенно не нужный в высокоуровневых языках.

Так что вопрос мой остается. Да, можнонаписатьнечитаемыйкодибезгоуту, но зачем нужен инструмент, который не может сделать ничего практически полезного, кроме создания этого самого кода? Зачем вводить могучий и ужасный goto там, где, может быть, чуть-чуть не хватало break с меткой?

спустя 14 часов [обр] Thirteensmay(17/157)[досье]
Даниэль Алиевский[досье] Затем что goto более универсален, хотите вы этого или нет, но желание гибкого перехода между произвольными блоками и внутри них, существует. В основном оно продиктовано необходимостью экономии интеллектуальных, временных, и пр. ресурсов. Goto можно использовать абсолютно структурно, а при необходимости извлечь дополнительную выгоду, обоснованно нарушив структуру. Структуризация - не священная корова, это лишь один из инструментов, очень полезный, но не идеальный. И сделать его идеальным не представляется возможным т.к. идеальная структура это хаос ;)
спустя 3 часа 19 минут [обр] Даниэль Алиевский(5/125)[досье]

Так и без goto можно нарушить структуру как угодно, просто это делать неудобно. Никто не мешает, например, написать большой switch и прыгать по его case-ам при помощи целочисленной переменной. Извратиться можно множеством способов, вплоть до прилинковки ассемблерного модуля.

Самый универсальный язык, как известно, ассемблер. Это же не значит, что его инструкции должны внедряться во все языки программирования. Хотя в некоторых языках, например, на которых пишутся OS, ассемблерные вставки уместны.

Я вот все жду конкретного ответа. Вот эта штука в PHP (или других более или менее высокоуровневых языках) удобнее (естественнее, эффективнее, проще и т.д.) реализуется при помощи goto, чем при помощи вышеперечисленных альтернатив. Похоже, не дождусь :)

Экономия интеллекта - святое дело, за это я люблю Perl, где можно за 5 минут написать ужасающего, но работающего монстрика. Но goto я в нем, кажется, ни разу не использовал :)

спустя 1 час 39 минут [обр] Thirteensmay(17/157)[досье]
Вы получили этот ответ, пример Юрий Насретдинов aka yUAC[досье], но что ответили ? - то что это подозрительно ! ;)
спустя 3 дня [обр] Даниэль Алиевский(5/125)[досье]

Thirteensmay[досье] Я ответил, что этот пример решается с помощью break с меткой. Пример действительно подозрительный, но совершенно аналогичная ситуация может возникнуть при наличии нескольких вложенных циклов с нетривиальной логикой управления.

Известна ли вам хоть одна ситуация, когда goto полезен для чего-то другого, кроме выхода из системы вложенных блоков - для которого достаточно break с меткой? В языках программирования с объектами и виртуальными методами? (При отсутствии таковых goto действительно бывает полезен для моделирования автоматов с различными состояниями - ибо альтернативой оказывается моделирование состояния при помощи сложных switch, неэффективно расходующих процессорное время и усложняющих логику.)

спустя 14 часов [обр] Thirteensmay(17/157)[досье]
Даниил, не решается он с помощью break с меткой, там нет системы вложенных блоков. Да, ситуация когда goto полезен для чего-то другого, кроме выхода из системы вложенных блоков известна, это представленный пример.
спустя 10 часов [обр] Даниэль Алиевский(5/125)[досье]
function do_some_processing()
{
    MyBlock: {
        $fp1 = fopen(...);
        $fp2 = fopen(...);
        $fp3 = fopen(...);

        ...

        if(!some_action()) {
            break MyBlock;
        }
        ...

        if(!some_other_action()) {
            break MyBlock;
        }
        ...

        return true;
    } // конец MyBlock

    // вот сюда мы и попадаем по break MyBlock
    
    fclose($fp1);
    fclose($fp2);
    fclose($fp3);

    return false;
}
Нечто подобное у меня реально встречалось на практике в Java. Хотя, конечно, не на уровне закрытия ресурсов. Открытые файлы лучше вообще не оставлять, а если оставлять, то этим должны заниматься финализаторы (или деструкторы) объекта, конструктор которого открывает файлы, а не какая-то там функция. В моей практике речь шла, если не ошибаюсь, о каких-то переменных, которым может быть либо присвоено разумное значение (и тогда надо вернуть его), либо, если алгоритм терпит неудачу, мы выходим из вычислительного блока с помощью break MyBlock и выполняем специальную обработку этой ситуации. Но нужно это довольно редко.
спустя 14 часов [обр] Thirteensmay(17/157)[досье]
Без дополнительного блока таки не обошлось. А теперь представьте что у нас не такая простейшая ситуация, а реальный большой кусок кода, some_action'ов в нем штук 50 (причем это не процедуры а блоки операторов), и постпроцессинг состоит не из трех операторов а скажем из 700, причем в зависимости от результатов some_action надо переходить к разным частям постпроцессинга. Сколько дополнительных блоков тогда придется ввести ?, сколько времени потратить на их выделение ? В результате еще поимеем дополнительные куски вида } } } } }, причем в полном соответствии с законами жанра эти куски будут с нарушением отступов. Goto при этом позволит как сэкономить время, так и как это ни странно, улучшить читаемость кода. Скажете надо перерабатывать структуру ? - будете абсолютно правы, но времени на это нет. Когда задача представляет собой большую какашку, которую до вас рожало еще 3 программиста, условия задачи постоянно меняются, начальство обоснованно ничего не хочет слушать по поводу переработки, но требует сроки, вопрос о структуре в этом случае поверьте мне практически не стоит.
спустя 25 минут [обр] Midnight Cat[досье]

Thirteensmay, ну ты и флудер. Развел такую полемику на пустом месте. И если уж приводишь цитаты с других ресурсов, то вставляй их полностью, а не те куски, которые тебе "удобнее":

Вот еще кстати давеча наткнулся: http://ru.wikipedia.org/wiki/GOTO

Например, GOTO был намеренно полностью запрещён в Java и Ruby. Вместе с тем, в Аде — одном из наиболее продуманных с точки зрения архитектуры языке за всю историю[3], GOTO всё же был оставлен.

Опять травокуры виноваты ? ;)

В этой статье только это предложение и говорит в пользу GOTO, да и оно сомнительно...
А вот критика по этому поводу более конкретна (с того же ресурса):

Оператор GOTO в языках высокого уровня является объектом критики, поскольку чрезмерное его применение нарушает иерархическую структуру программы и приводит к созданию нечитаемого «спагетти-кода». Впервые эта точка зрения была отражена в статье Эдсгера Дейкстры «Доводы против оператора GOTO»[1], который заметил, что качество программного кода обратно пропорционально количеству операторов GOTO в нём.
...
Формально доказано, что применение GOTO не является обязательным (то есть не существует такой программы с GOTO, которую нельзя было бы переписать без этого оператора с полным сохранением функциональности). Одним из доводов против GOTO является то, что в некоторых случаях программисты ставят GOTO, чтобы быстрее достичь желаемого результата (написать фрагмент программы с определёнными свойствами), в то время как отсутствие GOTO заставило бы их провести более внимательный анализ задачи, который обычно приводит к получению более ясного, эффективного и лучше организованного кода.

Там же "за" GOTO только лишь 2 оправданных применения: выход из нескольких вложенных циклов сразу и обработка ошибок, что в большинстве языков ООП есть.

PS. Создается впечатление, что Thirteensmay не привык глубоко продумывать какую-либо проблему и решает такие задачи "в лоб", отсюда и привычка к GOTO, но это ИМХО.
PSS. Thirteensmay, если тебе так нравится код с GOTO, попробуй разобраться в чужом коде, где > 2000-3000 строк и полно понапиханных GOTO. Может тогда ты поймешь, что с GOTO структурирование проги очень сильно нарушается, не говоря уже о трудности внесения изменений в код и поддержки.

спустя 51 минуту [обр] Thirteensmay(17/157)[досье]
Midnight Cat[досье] Пожалуйста, уважайте незнакомых людей, у нас принято обращаться на вы. Я не флудер, мы тут лишь подробно обсуждаем вопрос, я отстаиваю точку зрения что goto в некоторых крайне редких случаях может быть полезен, мне возражают, поэтому тема достаточно большая. Если вы будете продолжать в том же духе то за необоснованные обвинения модератор может вас наказать. Я привожу цитаты полностью, на куски их не рву, не надо обвинять меня в том чего я не совершал. Вы можете приводить любые другие цитаты также полностью, никто вам не запрещает. То что у вас создается впечатление что я не привык глубоко продумывать какую-либо проблему в нашем случае совершенно нормально, но если бы вы сами подумали немножко глубже то заметили бы что все это я отношу только к случаям нехватки времени. Мне не нравиться код с goto, ненадо передергивать, и пробовать разбираться в чужем коде в несколько тысяч строк с goto, мне пробовать не надо, я этим занимаюсь не первый год. То что вы считаете что goto сильно нарушает структуру кода говорит о том что вы, или те чей код вы разбирали, неразумно его использовали. Написать тяжелый код как мы выяснили раньше, свободно можно и без goto, goto тут непричем. Вообще если бы вы внимательно почитали тему сначала, вы бы поняли что все те вопросы которые вы предложили в своем посте мы уже разобрали, ненадо начинать заново, так что вопрос о том кто тут флудер остается открытым. И это, не нервничайте ;)
спустя 1 час 26 минут [обр] Midnight Cat[досье]

По теме топика:

Интересно было бы узнать комментарии разработчиков PHP о целях введения GOTO. Особенно если учитывать, что в последних версиях PHP делал большие шаги к ООП.

PS.Thirteensmay, согласен, нервничать тут ни к чему, поэтому этого и не делаю. Я лишь высказал свою точку зрения, т.к. не вижу смысла именно флудить в теме, даже потому, что тема озаглавлена как "зачем, как вы думаете, ввели goto в php", а не "есть ли смысл (и причины за и против) использования оператора GOTO в языках программирования".
По поводу "вы" и "ты". В той профессиональной среде, в которой я работаю, принято общение именно используя "ты", дабы не возводить дополнительные психологические (и др.) барьеры между людьми и сделать общение менее формальным и более продуктивным. Но, если именно Вас, уважаемый Thirteensmay, задевает и обижает общение на "ты", то могу только извиниться и общаться с Вами только, как Вы считаете, в "уважительной" манере (хотя, как показывает практика, обращение на "вы" или "ты" не отражает прямой зависимости к уважению). Подводя итог сказанного, "флудер" - это было не оскорбление, а констатация фактов (хотя если быть точнее, в споре о GOTO Вам больше подходит определение "троль").
Больше спорить с Вами не хочу, поэтому и не полностью отвечаю на Ваше сообщение.

спустя 40 минут [обр] Thirteensmay(17/157)[досье]

Midnight Cat[досье] Ого ! "троль" ? а еще какие слова вы знаете ? Вообще, что конкретно вы хотели сказать по теме ? Как вы думаете зачем было вводить goto ? Именно так она называется, я свое предположение высказал, каково ваше ? Кто после этого троль ? Шло вполне нормальное общение, но тут появился Midnight Cat[досье] и началась с.ачка, к чему бы это ? В вашей среде принято общаться на ты, вот и общайтесь там на ты, а здесь извольте как это общепринято.

Больше спорить с Вами не хочу, поэтому и не полностью отвечаю на Ваше сообщение

Да мы и спорить то еще не начали, вышел человек, запостил пару сообщений с оскорблениями, и в кусты. Показательно.

Модератору: не хотел, ну уж извиняйте, вынуждают.

спустя 2 часа 49 минут [обр] Midnight Cat[досье]
Вообще, что конкретно вы хотели сказать по теме ?

Thirteensmay, что конкретно я хотел сказать, а точнее узнать, я уже спросил в предыдущем своем сообщении.

Ого ! "троль" ? а еще какие слова вы знаете ? Как вы думаете зачем было вводить goto ? Именно так она называется, я свое предположение высказал, каково ваше ? Кто после этого троль ? Шло вполне нормальное общение, но тут появился Midnight Cat и началась с.ачка, к чему бы это ? В вашей среде принято общаться на ты, вот и общайтесь там на ты, а здесь извольте как это общепринято.

Не собираюсь отвечать на этот словесный ... выплеск эмоций. Получается, человек создал топик на интересующую его тему, а именно о goto (конечно, Вам виднее в каком регистре писать операторы и/или сообщения :) ), Вы, Thirteensmay, начали разводить здесь спор о том, нужен ли он вообще. А я высказав свое мнение о том, что Вы занимаетесь флудом (разговоры о том как помогает Вам goto, только потому, что у Вас нет времени кодить нормально и обдуманно, никак по-другому назвать не могу), получаюсь зачинщиком спора?!

PS. Thirteensmay, не мните о себе так много и не думайте, что моей целью было поспорить с Вами. Мне интересна эта тема, но очень неприятно, когда заходишь почитать какую-либо информацию, а получаешь пространственные рассуждения какого-нибудь "знатока" о его восприятии действительности как абсолютного и единственно верного. Вы даже сейчас, когда я уже сказал, что не хочу с Вами спорить, продолжаете требовать от меня какие-то ответы и бежите жаловаться зачем-то модератору. Вообщем, надоело мне это... простым, человеческим языком говорю ТЕБЕ - ОТВАЛИ!

спустя 1 час 2 минуты [обр] Thirteensmay(17/157)[досье]
Midnight Cat[досье] Хм, интересный вы, сначала обозвали меня флудером и тролем, а теперь отвали ? ;) Я конечно понимаю что на вопрос "Как Вы думаете зачем ввели goto ?" вы ответили "Надо узнать это у разработчиков PHP". Это конечно хороший ответ, вот только автор это спрашивал явно не у разработчиков PHP а у нас. Спор о том нужен ли goto вообще, инициирован не мной исключительно, и обсуждать этот аспект логично, т.к. ответ на этот вопрос напрямую помогает ответить на вопрос топика. Если разговоры о том как может помочь goto когда не хватает времени, вам кажутся флудом, то это значит что вы не можете или не хотите увидеть этот практический момент, прискорбно конечно, но это ваше дело, вот только не надо при этом катить на меня бочку, меня спросили назвать случаи когда goto может быть полезен - я назвал. А вы ? Ничего не предложив называете меня флудером ? Сказали что не хотите со мной спорить - не спорьте, держите слово, а я такого не говорил, поэтому отвечать на ваши выпады буду.
спустя 4 часа 10 минут [обр] Даниэль Алиевский(5/125)[досье]

Thirteensmay[досье] Сочувствую. Наверно, это оттого, что уж больно неказистый предмет вы взялись защищать. Мне тоже приходилось :)

А теперь представьте что у нас не такая простейшая ситуация, а реальный большой кусок кода, some_action'ов в нем штук 50 (причем это не процедуры а блоки операторов), и постпроцессинг состоит не из трех операторов а скажем из 700, причем в зависимости от результатов some_action надо переходить к разным частям постпроцессинга. Сколько дополнительных блоков тогда придется ввести ?, сколько времени потратить на их выделение ? В результате еще поимеем дополнительные куски вида } } } } }, причем в полном соответствии с законами жанра эти куски будут с нарушением отступов. Goto при этом позволит как сэкономить время, так и как это ни странно, улучшить читаемость кода.

Вот про это я и спрашиваю. Про реальный кусок кода. Я долго пытался придумать ситуацию, где полезен хотя бы break с меткой. Не придумал. Полез в реальный код весьма объемных Java-библиотек (много мегабайтов), нашел два случая. Оба случая неочевидны, один даже весьма специален - я там обходил какие-то ошибки Java-машины, связанные с некорректной обработкой исключений. (Сейчас точно не помню, искал несколько дней назад.)

А вы можете припомнить ситуацию, когда goto вам помог? Или кому-то другому? В чистом виде, где goto не сводится к выходу из очень сложного блока, где он строго эквивалентен break с меткой? Если нет, то можете хотя бы придумать такую ситуацию - но конкретную, некий алгоритм или задачу, которую можно здесь объяснить?

Разрешаю вам использовать любые допущения о контексте ситуации. Пусть задача срочная, пусть начальник дурак, пусть вы программируете не в нормальной оболочке, которая умеет расставлять отступы, а в Notepad, пусть вам наплевать на будущих читателей кода и на поддержку программы, пусть вы решили пренебречь даже собственным здравым смыслом - и возникло героическое намерение написать процедуру с 700 операторами только лишь постпроцессинга, пусть при этом надо сегодня за три часа и две банки пива сделать суперсрочный заказ - или, напротив, у вас есть месяц на предварительные размышления и полгода на реализацию гениального алгоритма. Хоть в какой-нибудь реальной ситуации может оказаться, чтобы goto сэкономил время программисту (или процессору), при наличии виртуальных методов и возможности break из блока любого уровня вложенности?

спустя 12 часов [обр] Midnight Cat[досье]

Не знаю, подойдет этот пример или нет, но goto использовал в написании батников. Но это другая история, хотя, тогда нужно было написать не важно как, но быстро + не было времени копаться в доках + несовершенство самого досовского языка так сказать. И даже в этом случае, использовал его для вывода информации для пользователя, а не для выполнения основного алгоритма.

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

ИМХО, нет. Выход из вложенных циклов делается за счет break, finally. Для всего остального есть function.

PS. А при условии, что Разрешаю вам использовать любые допущения о контексте ситуации. - можно и пустые циклы на миллион итераций писать вместо delay(1000).

спустя 2 часа 14 минут [обр] Thirteensmay(17/157)[досье]

Midnight Cat[досье] Ну вот блин ну совершенно же другое дело, с таким с вами хочется нормально общаться ;)

Даниэль Алиевский[досье] Не, ну break с меткой то полезен без сомнения, если он в языке есть, а вот если нет то goto, мы это уже разбирали, + примеры я привел ниже, и дело даже не в том что их можно переписать без goto, бесспорно можно. Дело в том что в процессе разработки, к моменту достижения того места где стоит goto, большая часть кода уже написана, поблочно оттестирована, и все переписывать и перетестивать заново лишь из за желания уйти от goto помоему не разумно, тем более что в представленных ниже случаях goto вполне удобочитаем и понимаем. Ну ладно, допустим даже все перетестивать и переписывать не надо, но некоторое время потратить на реструктуризацию всеже придется, а когда голова уже под завязку забита, и через 15 мин. задачу надо во чтобы то ни стало завершить, тогда вот да, goto как это представлено ниже. А если еще решение является прототипом, т.е. предназначено лишь для проверки принципиальной возможности работы, и в последствии скорее всего будет переписано, то тогда вообще помоему польза от goto налицо.

  -- проход по всем изменениям транзакции
  for chg in (select t.rpl_change_id,
                     t.is_arh
              from
              (select c.rpl_change_id,
               0 as is_arh
               from t_rpl_change c
               where c.transaction_id = itrx
                 union all
               select ac.rpl_change_id,
               1 as is_arh
               from t_rpl_arh_change ac
               where ac.transaction_id = itrx) t
               order by t.rpl_change_id)
  loop
    recintrans := recintrans + 1;
  
    -- определение атрибутов изменения
    if chg.is_arh = 0 then
      change_table := 't_rpl_change';
      changeval_table := 't_rpl_change_value';

      select c.table_id, c.change_type, dt.is_apply
      into table_id, change_type, applicable
      from t_rpl_change c,
           t_rpl_def_table dt
      where c.rpl_change_id = chg.rpl_change_id
      and dt.rpl_def_table_id = c.table_id;
    else
      change_table := 't_rpl_arh_change';
      changeval_table := 't_rpl_arh_change_value';

      select ac.table_id, ac.change_type, dt.is_apply
      into table_id, change_type, applicable
      from t_rpl_arh_change ac,
           t_rpl_def_table dt
      where ac.rpl_change_id = chg.rpl_change_id
      and dt.rpl_def_table_id = ac.table_id;
    end if;

    -- применение изменения
    begin
      -- фильтрация неприменяемых изменений
      if applicable = 1 then
        appflag := 1;
        
        case change_type
          -- INSERT
          when 1 then
            execute immediate create_apply_code(1, table_id,
              changeval_table, chg.rpl_change_id);
          -- UPDATE
          when 2 then
            execute immediate create_apply_code(2, table_id,
              changeval_table, chg.rpl_change_id);
          -- DELETE
          when 3 then
            execute immediate create_apply_code(3, table_id,
              changeval_table, chg.rpl_change_id);
        end case;
      else
        appflag := 2;
      end if;
    exception
      -- если ошибка применения изменения
      when others then
        oerror := 'Ошибка применения изменения ' || chg.rpl_change_id
          || ': ' || SQLERRM;
        tolog(1, oerror);
        
        rollback;
        goto fin;
    end;

    -- отметка изменения как примененного
    execute immediate 'update ' || change_table
      || ' set is_apply = ' || appflag || ' where rpl_change_id = ' || chg.rpl_change_id;
  
  end loop;
  
  -- фиксация транзакции
  begin
    commit;
    applyrec := applyrec + recintrans;
  exception
    -- если ошибка фиксации транзакции
    when others then
      oerror := 'Ошибка фиксации транзакции ' || itrx
        || ': ' || SQLERRM;
      tolog(1, oerror);

      rollback;
  end;

  << fin >>
  CHTR_DISABLE := 0;
  if usearh = 1 then
    tolog(1, 'Задействовано архивное хранилище');
    begin
      select 1 into usearh
      from t_rpl_arh_change
      where rpl_change_id = startblockchange;
    exception
      when NO_DATA_FOUND then
        -- нет новых или удалено ?
        -- извлечение номера последнего удаленного изменения
        select value_ into lastch
        from t_parametr
        where parametr_id = 56;

        -- PacketStatus:
        if startblockchange > lastch then
          cblappend('EMPTY');
        else
          cblappend('ERROR');

          errstr := 'Запрашиваемое изменение '
          || startblockchange || ' не существует (было удалено)';
          tolog(1, errstr);
        end if;

        goto afterfill;
    end;
  
    -- наполнение из архивного хранилища
    cblappend('NORMAL');
    cblfill(1, iforserver, startblockchange, lastblockchange);
  end if;
  
  -- если архивное хранилище не было зайствовано
  if usearh = 0 then
    cblappend('NORMAL');
  end if;
  
  -- наполнение из основного хранилища
  cblfill(0, iforserver, startblockchange, lastblockchange);

  << afterfill >>  
  -- вычисление и размещение Checksum
  -- со смещения 35 (начиная с 1, заголовок + MD5) до конца
  dbms_lob.createtemporary(tmpblob, false, dbms_lob.call);

Тут использование goto похоже на справление малой нужды под кустом, плохо ? в теории да, но на практике выручает.

Даниил, а что касается как вы выразились "чистого" использования goto, т.е. не для выхода из вложенных блоков, то тут во первых надо понимать что чистое использование в подавляющем большинстве случаев как раз и предполагает выход из блоков, изначально, то что break с меткой в последствии стал дублировать эту функциональность это я бы сказал говорит о избыточности break с меткой, я понимаю что концептуально break более красив, но как мы убедились порождает дополнительные блоки, так что тут не все гладко. А во вторых, если всеже рассматривать ситуации использования goto не для выхода из вложенности, то лично у меня в практике был только один такой случай, както раз писал процесс работы со сканером, там низкоуровневая чисто C библиотека, десяток инициализационных действий (процедур), а потом еще десяток рабочих процедур, они если что возвращают код ошибки, и ее конечно надо обрабатывать и дальше не идти, а также освобождать ресурсы в конце, т.е. ситуация очень похожа на пример Насретдинова, так вот, я недолго думая также свел ее к структуре с одной меткой, никаких дополнительных блоков, генерации и обработки исключений делать не стал, зачем лишние телодвижения если все нормально без них ? Удобочитаемость как мы видим на примере Насретдинова нисколько не страдает. Вообще в своей осознанной профессиональной практике, если не учитывать колледжи и институты, скажем за последние 10 лет, я родил порядка двух десятков goto, 19 из которых были типа представленных выше мной 2 примеров, т.е. выход из вложенностей, и лишь один, типа примера Насретдинова.

Даниил, если не рассматривать случаи с выходом из вложенностей, то единственное чем break с меткой отличается от goto, это то что он порождает дополнительный блок, он ему нужен в любом случае, но если это не выход из вложенностей то этот блок как правило особо ни чем не мешает, и даже более того, логически полезен. Тут стоит признать вашу правду. Но всеже оговорю, дополнительный блок тем не менее появляется, goto таких ограничений не налагает, а если учесть что goto в основном используется для выхода из вложенностей то тут дополнительные блоки уже могут помешать как я описал в предыдущем своем посте вам.

В представленных мной выше двух примерах goto можно обойти также за счет выделения и введения дополнительных блоков, но потребуется время на их выделение и комментирование, иначе странно будет видеть начало какого то блока где он на первый взгляд не нужен. И чтобы этот блок выделить надо просмотреть и понять весь окружающий код, что опять время. Мужики, я вам далдоню это уже в который раз, да goto можно обойти, реструктуризовав и переосмыслив код, но на это ТРЕБУЕТСЯ ВРЕМЯ, и доп. моральные усилия, а их может не быть. Написать с первого раза качественно большой кусок кода не всегда получается, на его переделку требуется время, goto может быть компромиссом. А вы все можно обойти, да можно обойти, можно, кто бы спорил, деньги за время потраченное на реструктуризацию вы мне платить будете ? а то заказчик чтото не хочет. А с чисто теоретической точки зрения вы правы, не спорю, но я вам не про теорию, а про практику.

Ну и на последок, урок из сообщений Midnight Cat[досье] всеже надо извлеч, зерно тут заключается в том что да Даниил, мы с вами похоже сильно увлеклись лишь одним из моментов и не обсуждаем возможные другие, посему попытаюсь исправить эту ситуацию, подитожу наше обсуждение и попробую предложить нечто новое. Итак, предлагаю список возможных причин введения goto:

1. Расширение гибкости языка.
Это то что мы с вами тут усиленно до этого обсуждали, я всеже остаюсь при мнении что goto делает язык гибче и из этого в редких случаях можно извлеч пользу, см. обсуждение выше.

2. Ошибка разработчиков.
Т.е. можно предположить что goto не имеет никакой пользы, или его польза многократно перекрывается вредом. А разработчики не учли этого момента.

3. Преемственность и наследственность.
Goto введен т.к. он присутствует в массе др. языков, разработчики пришедшие из этих языков, или одновременно программирующие на нескольких, обладают накопленным багажем практики программирования с goto, т.е. устоявшейся привычкой, и отсутствие оного пусть и по началу, но раздражает. Также т.к. goto наиболее широко распространен, он может использоваться как единый инструмент решения типичных ему задач, что также может быть немаловажно при мультиязычном программировании.

4. Совместимость.
Например можно предположить что разработчики хотят нативно внедрить в PHP какую либо большую библиотеку алгоритмов, из др. языка обладающего незамысловатым синтаксисом, но с goto, который там достаточно часто используется. Библиотека велика и сложна для ручного переписывания, в тоже время написать парсер и конвертер не сложно т.к. язык незамысловат, единственное что смущает в этом случае - отсутствие goto в PHP. В это конечно верится слабо, но если попытаться хоть чуть развить мысль то можно предположить например следующее: Нонче модно забавляться виртуальными машинами, что если в недрах PHP замыслили нечто подобное, язык ВМ при этом очевидно будет прост, и скорее всего с goto, хотя и с др. конструкциями типа IF/ELSE и подобными. Goto в нем может использоваться как неотьемлемая часть т.к. язык низкоуровневый и прост, а также как средство совместимости с др. языками, если предположить что ВМ будет совместима с несколькими языками. Таким образом у нас появляется возможность перекладывать программу с одного языка на другой, пусть и с частичной потерей оригинального синтаксиса, или просто восстанавливать оригинальный код, куда более качественно чем существующие дисассемблеры. Весьма я бы сказал сомнительное предположение, но всеже вполне возможно чтото на основе этой идеи. Травокуры отдыхают ;)

Давайте если хотите обсудим эти варианты, также не стесняйтесь предлагать свои. А то я тут практически один выдвигаю предположения и их отстаиваю, а все остальные ходят и фукают, знаете ли мне так не очень интересно ;)


24464570528145--

спустя 2 часа 34 минуты [обр] Прокаев2(13/35)[досье]

Вы так и не подрались горячие финские парни ;)

я давно читал обсуждение http://www.procata.com/blog/archives/2004/07/29/goto-in-php/
особо издевательски (в приложении к интерпретатору)
звучит "it can be faster than other control structures" ))

Thirteensmay прав. Когда приходится сводить/править код(написанный иногда весьма дерьмово)
обычно нет ни желания/ ни времени на рефакторинг. Работает (пусть даже с goto)- не трогай!

спустя 12 минут [обр] Thirteensmay(17/157)[досье]
ну вот какраз сейчас пишу импорт одной очень очень кривой и большой базы, до меня его еще 2 чела писало недописало, мне спихнули, работа разовая, goto еще не приплел, но если возникнет малейшая необходимость сразу же заюзаю и задумываться не буду.
спустя 21 минуту [обр] Thirteensmay(17/157)[досье]
потому что 90% того что в этом импорте есть, гораздо срашнее goto.
спустя 3 часа 23 минуты [обр] Midnight Cat[досье]
"Драться" интересно, только хлопотно. :)
Скажу так - я не до конца выразил свою точку зрения: использование goto в полном цикле разработки программы/модуля/библиотеки/ и т.д. полностью исключается возможностями и конструкциями языка программирования (только не надо на меня тут кидаться и приводить особо извращенные примеры языков :) ).
В каких-то ситуациях можно и даже нужно использовать goto, что зависит от конкретного наличия/отсутствия ресурсов, будь то время, большой объем работ и пр. Просто для начинающих и(или) даже среднего уровня программеров goto и его использование может показаться панацеей от проблем с продумыванием и четкой структуризацией кода в большинстве случаев, что, я считаю, очень плохо и ведет к снижению уровня и культуры программирования. Вот почему я так негативно и категорично высказываюсь против goto. Как говорится "Эти ягоды есть можно? - можно, только отравитесь" (с).
ЗЫ. Все должно быть в меру!
спустя 1 час 19 минут [обр] Thirteensmay(17/157)[досье]

Midnight Cat[досье] Тут я с вами соглашусь без оговорок, выше я также говорил:

дело в том что правильно пользоваться goto надо уметь, нужен некоторый опыт, у начинающих программистов его нет, поэтому в подавляющей массе учебной литературы goto гнобят, и правильно, а то начинающие такое начинают c goto воротить что не в сказке сказать.

Между тем продолжу выдвижение идей. Очевидно существующее в PHP решение, break с параметром как заметил Алексей Полушин[досье] не удобно, более того предположу что оно обладает существенным негативным побочным эффектом, при выходе например из блока 3 уровня вложенности на 1, при добавлении блока во второй уровень, вложенные выходы нарушаются. Кроме того это решение обладает и др. недостатками рассмотренными выше. Благодаря Даниэль Алиевский[досье] свет увидел следующий вопрос:

Зачем вводить могучий и ужасный goto там, где, может быть, чуть-чуть не хватало break с меткой ?

Некоторые аспекты ответа на него мы уже рассмотрели, предлагаю к рассмотрению еще один, а также очередной пункт списка:

5. Простота реализации.
Возможно что реализация goto в PHP была проще чем реализация break с меткой (именованных блоков).

спустя 10 часов [обр] Midnight Cat[досье]

Thirteensmay[досье], что-то я не понял с:

при выходе например из блока 3 уровня вложенности на 1, при добавлении блока во второй уровень, вложенные выходы нарушаются

пример кода?

спустя 2 часа 9 минут [обр] Thirteensmay(17/157)[досье]
...
{
  some1();  
  {
    ...
    {
      break 3;
    }
  }
  some2();  
}
finalize();
По break 3 мы попадаем на finalize(), все хорошо. Но что если позже выявилась необходимость some1()..some2() заключить в дополнительный блок ? тогда break 3 надо переделывать на break 4. Т.е. каждый раз при введении дополнительного блока надо не забывать просматривать все вложенные блоки на предмет наличия и корректировки break ?
спустя 1 час 5 минут [обр] Midnight Cat[досье]
Thirteensmay[досье], эта тема уже склоняется к рефакторингу. Не думаю что "в крайне редких случаях", когда break заменяет отсутствующий goto или когда применение goto оправдано с каких-либо позиций, переписывание значения вложенности break'а принципиально с позиции удобства. Все таки "опасность", которую может породить использование goto и привыкание к нему (обсудили это ранее), перевешивает неудобство изменения одного параметра break'а.
спустя 1 час 5 минут [обр] Thirteensmay(17/157)[досье]
Midnight Cat[досье] Дело тут не в неудобстве изменения, а в том что про него очень легко забыть, в результате после внесения совершенно безобидного изменения, работоспособность целой процедуры может быть нарушена. Если вместо break с параметром использовать goto или break с меткой, то такой проблемы не возникает. А вот goto или break с меткой мы уже обсудили.
спустя 2 часа 16 минут [обр] Даниэль Алиевский(5/125)[досье]

Thirteensmay[досье] У меня такое ощущение, что все ваши контрдоводы несостоятельны, если в языке есть break с меткой. И у Насретдинова, и в вашем могучем и ужасном примере (насколько я успел понять за 2 минуты) goto полностью эквивалентен "break метка", если ввести и пометить соответствующий блок. Причем ввести такой блок настолько просто, что, кажется, это можно сделать даже автоматически. Да и вручную никакого времени на это не надо - даже я, не знающий языка (кстати, что за язык у вас? простите дремучее невежество), вижу, куда надо добавить begin и end. А в чем вред от дополнительного блока, я решительно не вижу. Даже в существующей, самой устрашающей программе объявление такого блока просто чуть-чуть улучшит читаемость нечитаемого кода. Что плохого?

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

Это пример типа Насретдинова? Так тут break с меткой и проще, и понятнее. А знаете ли вы случаи, когда нужен именно goto, не эквивалентный break с меткой? Я только об этом спрашивал.

Лично мне на Паскале приходилось применять goto в чистом виде, не эквивалентном break с меткой. Это был автомат для обхода периметра связной частицы на битовой матрице. Цитирую:

R_:
   SPSide:= SPBottom;
   if (SPX=x0) and (SPY=y0) and (SPSide=side) then goto Exit_;
SR_:
   if UserRoutineActive then AnyProc (UserRoutine);
   IBAGoRightDown;
   if IBAGetBit then begin SPXpYm; ChMaxX; ChMinY; ChMaxXmY; goto D_ end;
   IBAGoUp;
   if IBAGetBit then begin SPXp; ChMaxX; ChMaxXpY; ChMaxXmY; goto R_ end;
   IBAGoLeft;

U_:
   SPSide:= SPRight;
   if (SPX=x0) and (SPY=y0) and (SPSide=side) then goto Exit_;
SU_:
   if UserRoutineActive then AnyProc (UserRoutine);
   IBAGoRightUp;
   if IBAGetBit then begin SPXpYp; ChMaxX; ChMaxY; ChMaxXpY; goto R_ end;
   IBAGoLeft;
   if IBAGetBit then begin SPYp; ChMaxY; ChMaxXpY; ChMinXmY; goto U_ end;
   IBAGoDown;

L_:
   SPSide:= SPTop;
   if (SPX=x0) and (SPY=y0) and (SPSide=side) then goto Exit_;
SL_:
   if UserRoutineActive then AnyProc (UserRoutine);
   IBAGoLeftUp;
   if IBAGetBit then begin SPXmYp; ChMinX; ChMaxY; ChMinXmY; goto U_ end;
   IBAGoDown;
   if IBAGetBit then begin SPXm; ChMinX; ChMinXpY; ChMinXmY; goto L_ end;
   IBAGoRight;

D_:
   SPSide:= SPLeft;
   if (SPX=x0) and (SPY=y0) and (SPSide=side) then goto Exit_;
SD_:
   if UserRoutineActive then AnyProc (UserRoutine);
   IBAGoLeftDown;
   if IBAGetBit then begin SPXmYm; ChMinX; ChMinY; ChMinXpY; goto L_ end;
   IBAGoRight;
   if IBAGetBit then begin SPYm; ChMinY; ChMinXpY; ChMaxXmY; goto D_ end;
   IBAGoUp;
   goto R_;

4 состояния, между которыми автомат переключается, и без goto на Паскале или C это эффективно не решается. Но на Java уже решается. Здесь это превратилось в обычный цикл вот таких методов:

            void next8() {
                if (!atMatrixBound()) {
                    if (diag()) {
                        lastShiftInfo = mover.diagonal;
                        mover = lastShiftInfo.newMover;
                        return;
                    }
                    if (diagLeft()) {
                        lastShiftInfo = mover.straight;
                        return;
                    }
                    straightBack();
                }
                lastShiftInfo = mover.rotation;
                mover = lastShiftInfo.newMover;
            }

Используется объект mover, перемещающий позицию к следующему пикселу. У него 4 реализации, соответствующие 4 помеченным фрагментам Паскаля, а виртуальные методы diag(), diagLef() и straightBack() перемещают позицию по-разному для каждой из 4 сторон квадратного пиксела. На смену goto пришла диспетчеризация виртуальных методов, которая прекрасно оптимизируется транслятором и на машинном языке превращается в очень простые call. И вообще открылись невиданные ранее возможности оптимизации - виртуальные методы могут использовать самые разные оптимизации в зависимости от способа хранения битов.

По вашим пунктам 1-4.

1 - до сих пор вы не доказали, что язык гибче с goto. К автомобилю можно присобачить сбоку метлу, но надо привести по крайней мере один пример ситуации, когда эта метла будет полезна водителю.

2 - это не ошибка для старых языков, где не было ООП. При наличии виртуальных методов и break с меткой goto - ошибка. Так почему разработчики PHP простому и кошерному break с меткой предпочли goto?

3 - по-моему, это было актуально лет 30 назад, когда люди переходили с Фортрана и Алгола на Паскаль и C. Вот уже минимум 30 лет goto активно осуждается, и все программы, мало-мальски достойные перевода на новый язык (тем более на скриптовый PHP), не применяют goto или применяют его крайне ограниченно. Разве что как выход из сложного блока, но это решает break с меткой. То же самое относится к пункту 4.

5 - не верю я, что разработчики PHP ввели goto из лени. По-моему, наличие goto принципиально усложняет, а не упрощает трансляцию, по крайней мере по части оптимизации кода. А вот добавить метку к break, вроде бы, вообще было тривиально, раз уже были break с уровнем вложенности.

спустя 24 минуты [обр] Алексей Полушин(62/231)[досье]
По последнему пункту - какое усложнение трансляции по части оптимизации кода в интерпретаторе ?
А вот break в PHP есть только для циклов, поэтому я в первом примере и вставлял фиктивный цикл do ... while(0). Видимо, разработчикам действительно было проще добавить goto, чем break из помеченого блока.
спустя 2 часа 20 минут [обр] Даниэль Алиевский(5/125)[досье]

Насчет оптимизации я и правда загнул. Ясно же, что там все компилируется в какой-нибудь байт-код, в котором, вероятно, goto был с самого начала. И оптимизация строится совсем по другим принципам, чем те наивные соображения, которые я попробовал привести.

Но все-таки рассуждения насчет "проще" какие-то странные. По сравнению с поддержкой самого языка, библиотек и всего прочего добавление помеченных блоков не должно быть какой-то катастрофой. Тем более если есть и метки (для goto), и блоки.

спустя 1 час 18 минут [обр] Thirteensmay(17/157)[досье]

Даниэль Алиевский[досье]

  1. Ну break с меткой в PHP нет, а хоть бы и был, невозможно перейти от одного произвольного оператора к др. просто так, необходимо вводить дополнительный блок. Break с меткой решает проблему произвольного перехода, но не элементарно. Goto может быть абсолютно аналогичен break с меткой, в добавок к этому он позволяет элементарно осуществлять переход. Скажете мелочи ? Ну а что, break с меткой по сравнению с break с параметром тоже не бог весть что, всего то надо считать скобочки. Считаю введение goto полезным, т.к. его преимущество над break с параметром очевидно, и слегка более полезным чем введение break с меткой, т.к. все возможности break с меткой сохраняются, + кое где, чуть чуть можно сэкономить.

Думаю Даниил надо нам эту лавочку сворачивать (goto vs break), все что можно было мы тут раскопали и заняли как говорится крайние позиции, ни вам ни мне отступать некуда, Вы никогда не признаете что введение дополнительного блока может быть пустой тратой время, даже если вам придется просматривать тысячи строк кода, а я не признаю что goto сам по себе вреден даже если придется разгребать страшную кашу с сотнями goto, потому что ее можно спокойно устроить и без goto.

  1. Вот здесь кстати моя позиция для вас может проясниться. Вы считаете что в языках с ООП goto не нужен. И в принципе правы, если рассматривать чисто ООП, но дело в том что современные языки не являются чисто ООП, они универсальны, позволяют использовать процедурное программирование ничем не хуже, и ООП без него никуда. Я редко прибегаю к ООП и подавляющую часть задач решаю в процедурном стиле, это часто оказывается быстрее и проще. Поэтому с моей точки зрения введение goto в этих языках при отсутствии достойных альтернатив не является ошибкой. Break с меткой достойная альтернатива, но goto всеже капельку лучше.

Самой большой текущей проблемой goto является отрицательный пиар, инерционность общества, приписывание современному goto семантики старого goto. А ведь он давно ограничен, бел и пушист, рассматривайте goto как более оптимальный (за счет не выдвижения дополнительных требования к блокам) вариант break с меткой, по крайней мере я его использую именно так, тогда поймете в чем его прелесть.

  1. Ну я ж вам не из 30 лет назад этот пост пишу, все эти 30 лет goto не только осуждается, но и активно поддерживается, вводится в новые языки, и будет поддерживаться в перспективе. В настоящее время goto имеет наибольшее распространение, благодаря его повсеместному гноблению о нем с пеленок знает каждый программист, а что break с меткой, в лучшем случае 30%. Поэтому в первую очередь imho вспоминается именно goto. Так что вопрос преемственности думаю сбрасывать со счетов не стоит.
  1. Это лишь догадка, бог его знает как оно у них там все устроено, и каковы особенности. С теоретической точки зрения реализация goto и break с меткой ничем не отличается, это всего лишь переход по адресу/ссылке, созданной на этапе разбора кода, или поиск метки если интерпретатор пускается в исполнение сразу же. Однако можно предположить что break с меткой может быть сложнее за счет реализации концепции именованных блоков, к тому же замечание Алексей Полушин[досье] тоже наталкивает на определенные мысли, вряд ли PHP написано абсолютно концептуально чтобы так просто расширить определение блоков, упрощения там скорее всего есть. А что касается "По сравнению с поддержкой самого языка, библиотек и всего прочего..." могу вам сказать Даниил, что в ваших рассуждениях вообще есть выраженный концептуально-теоретический окрас, складывается такое впечатление что о например сроках или ресурсах вы можете задумываться меньше чем о идеалогической стройности, законченности и архитектурной красоте. Я вам завидую, PHP'шники возможно тоже.
спустя 14 минут [обр] Thirteensmay(17/157)[досье]
Ах да, Даниэль Алиевский[досье] вы спрашивали по поводу языка, это http://ru.wikipedia.org/wiki/PL/SQL
спустя 3 часа 23 минуты [обр] Василий Свиридов(53/175)[досье]
В ядре линукс используется GOTO. И ничего пока... http://kerneltrap.org/node/553/2131 вот тут goto-срач шестилетней давности... Аргументация обеих сторон сильно с тех пор не поменялась :) Дайкстра с Виртом осудили GOTO, и с тех пор все преподаватели информатики вдалбливают это своим студентам. Хотя как обычно вина не в инструметнте, а в руках и мозгах применяющего этот инструмент.
спустя 20 часов [обр] Даниэль Алиевский(5/125)[досье]
Thirteensmay[досье] Нда, вот что делает регистр :) Я на SQL почему-то никогда не программировал, но программы, конечно, видел. Однако все примеры, которые я смотрел, были набраны в верхнем регистре. И были в основном короткими. А тут вижу - длинная программа, набранная в нижнем регистре, вроде похоже на SQL, но ведь топну в лужу - брызги полетят... Спасибо :)
спустя 18 минут [обр] Даниэль Алиевский(5/125)[досье]

Thirteensmay[досье]

  1. Вы, конечно, правы, эта holy war не бог весть какая полезная, но, если честно, для меня это просто отдых :) По сравнению с прочими вопросами, которые приходится решать, поговорить о goto на редкость приятно. С вашего разрешения, я все-таки отвечу, ну а отвечать ли далее - решайте сами.

Почему вы утверждаете, что break с меткой решает проблему произвольного перехода? Если я что-то в чем-то понимаю, то он никак не эквивалентен по мощи goto. Перейти можно только вперед, и не куда попало, а лишь на более высокоуровневый по вложенности синтаксический блок. С помощью break с меткой, например, никак не удастся реализовать приведенный мной выше автомат обхода периметра. Переход, который обеспечивает break с меткой, всегда достижим иными средствами - а именно, оформлением соответствующего куска в виде отдельной функции (если язык позволяет выйти из функции в любой точке, как все известные мне языки). Более того, отдельная функция обычно и является правильным архитектурным решением, поэтому break с меткой нужен чрезвычайно редко. Но иногда, по моему опыту, он все-таки бывает уместен. Хотя не исключаю, что это лишь результат плохой продуманности. Вот более мощный goto - он, опять же по моему опыту, не нужен решительно никогда.

  1. Я говорил скорее не об ООП, а об очень конкретном механизме виртуальных методов, который позволяет решить те задачи, для которых goto действительно абсолютно необходим. С этим я столкнулся в приведенном примере. На самом деле дело тут не в ООП, а в концептуальном наличии указателя на функции (или эквивалента). В чистом C мой пример тоже можно переписать без goto, воспользовавшись такими указателями, и это, как и в Java, будет гибче и так же эффективно, как решение с goto.
  1. Вы правильно угадали, у меня в последнее время, слава Богу, была возможность думать об идеологической стройности. И благодаря этому я часто убеждался, что идеологически правильное решение требует меньшего расхода времени, чем неправильное. Русская поговорка - тише едешь...

В переводных учебниках по ООП, паттернам и антипаттернам проектирования, просто по языкам про это регулярно пишут: правильный подход к программированию практически всегда окупается сторицей.

спустя 1 день 13 часов [обр] Алексей Полушин(62/231)[досье]
Кстати, есть мнение, что возможность выхода из функции в произвольной точке тоже не есть хорошо. http://habrahabr.ru/blogs/complete_code/40841/
спустя 5 часов [обр] Thirteensmay(17/157)[досье]

Алексей Полушин[досье] Ну классика. По моему личному мнению это даже хуже goto, по крайней мере с goto особых проблем в моей практике не было, а вот из-за процедур со множественными точками выхода шарахаться приходилось. Относительно недавний случай - надо было потестить время исполнения кусков нескольких процедур, не долго думая - добавляется засечка времени в начале и подсечка в конце, и опа... оказывается выход есть не только через конец, были маты. Кстати в качестве быстрого решения - return'ы заменил на goto fin, а вот не было бы goto (break) - пришлось бы потрахаться ;) Я конечно понимаю что это из области создать себе проблему а потом героически ее решать, но реальность такова.

Даниэль Алиевский[досье] Тише едешь... это конечно хорошо, но ведь программирование может быть еще и зарабатыванием денег, а тут чаще выигрывает тот кто быстрее обернется. Я с вами согласен в том плане что при высокоуровневом подходе использование goto в общем не эстетично. Но к сожалению практика вносит свои коррективы. Вот взять того же Вирта например, уважаемейший человек, но за отсутствие ';' после end перед else похвалить никак не получается (я понимаю почему ему пришлось так сделать), и ведь это не по недосмотру, а вот других гнобить за goto - это можно, это пожалуйста. Нисколько не хочу умолить его заслуг, это просто показывает что даже лучшим из нас, несмотря на все свое мировоззрение, приходится прогибаться под реальность и практику в которой ресурсы ограничены, а продукт надо таки выпускать в срок. Есть в нашей среде такая распространенная болезнь - неадекватное стремление к идеалу. Решение задачи не может быть и не должно быть идеальным, отказ от goto это шаг в сторону идеализма. Вы конечно можете считать что это просто улучшение, но не забывайте что любая медаль имеет свою обратную сторону. Лично мне (и я не один такой) это улучшение не нужно, любые цели при разумном подходе решаются и без этого шага, а при неразумном подходе этот шаг все равно ничем не поможет.

спустя 9 часов [обр] Даниэль Алиевский(5/125)[досье]

Thirteensmay[досье]
Может быть, возможность выхода из функции где угодно и не есть прекрасно, но сравнивать это с goto даже смешно. Эта возможность в той или иной форме поддерживается всеми известными мне языками, при этом широко используется во множестве классических, коммерческих и академических модулей. Да, возможно, злоупотреблять этим не следует, однако сравнение явно неадекватное. Ваш пример с измерением времени решается тривиально в любом языке, поддерживающем try...finally. Не говоря уже о том, что измерение скорости работы либо следовало бы закладывать в архитектуру процедуры изначально (я обычно так и делаю для долгоиграющих алгоритмических процедур), либо нужно использовать профайлер, который обеспечивает то же самое (и многое другое) на более высоком уровне. Кстати говоря, измерить время работы блока, из которого возможен goto куда угодно и с какими угодно целями, все же куда труднее, чем время работы блока, который может завершиться только через break или return.

Насчет зарабатывания денег и "кто быстрее обернется" - не путаем ли мы понятия? Чтобы заработать деньги, собственно говоря, вообще не обязательно программировать. А среди тех, кто программирует (или красит заборы, или пишет романы) вовсе не обязательно больше заработает тот, кто делает свое дело лучше других. Мне кажется, этот критерий - возможность больше заработать - вообще некорректно применять в таких обсуждениях. Я могу лишь аргументировать вопросы о том, как программировать лучше - т.е. эффективнее с точки зрения соотношения затраченного времени и полученного результата. Это более или менее поддается измерению. Я уже несколько раз говорил о том, что в моей практике почти не было случая, чтобы goto ускорил или упростил процесс разработки - кроме тех ситуаций, когда он использовался как строгий эквивалент break с меткой в силу отсутствия последнего. Хотя я привел единственный известный мне пример - но он уже бесполезен в ООП-языках. Вы пока, кажется, не привели ни одного примера.

Не думайте, что я говорю только об "идеальных решениях". У меня самого полно сырого кода, который подлежит оптимизации, документированию, улучшению и пр. - и эти улучшающие преобразования действительно иногда происходят, вплоть до полного выкидывания неправильного кода. Приходится прибегать к множеству компромиссов. Однако в случае goto я не вижу ни единой ситуации, когда эта возможность могла бы хоть чему-то помочь. Ну разные бывают компромиссы в автомобиле, но ведь к нему не приделывают сбоку метлу?? Или, если ближе к теме, подкову, в память о временах, когда без подков ездить по дорогам было небезопасно для лошади.

спустя 11 часов [обр] Thirteensmay(17/157)[досье]
Даниэль Алиевский[досье] Ну вы же не используете goto (не привыкли его использовать), поэтому и не видите ситуаций когда он может быть полезен, вы привыкли обходиться без него, для вас породить дополнительный блок, или просмотреть пару сотен строк кода на предмет где его породить, или покурить документацию по очередному языку на предмет какой же аналог goto в нем есть, даже в условиях нехватки времени, или когда задача в принципе не требует структуризации, - совершенно нормально, у вас нет другого выхода. Я же goto изредка использую, поэтому в отличие от вас мне есть с чем сравнивать, goto позволяет не делать лишних телодвижений. Даниил, я вам и примеры приводил, и написал уже много, но вы по прежнему "не видите ни единой ситуации, когда goto мог бы хоть чем-то помочь", потому что вы не привыкли так делать, это не ваш подход. Мы с вами не первый раз беседуем, вы в очередной раз себя ограничили, а я в очередной раз предлагаю смотреть на мир шире.
спустя 45 минут [обр] Алексей Полушин(62/231)[досье]
Ну очевидно, что никто никого в своей правоте не убедит :) Может лучше вернуться к обсуждению Иудаизм: фундаментальные вопросы ? Там интереснее было, чем какой-то goto. Глобальные вопросы.
спустя 4 дня [обр] Даниэль Алиевский(5/125)[досье]

Thirteensmay[досье] Я не использую goto по более банальной причине: в языке Java, на коем я сейчас программирую, его попросту нет :) Язык, конечно, несовершенный, конечно, не один раз мне приходилось "натыкаться" на ограничения (вроде отсутствия передачи аргумента примитивного типа по ссылке) и сетовать, что авторы этого не предусмотрели (вплоть до вполне открытых обращений к их базу ошибок и рекомендаций), но вот goto ни разу вспомнить ни пришлось. Поэтому и ввязался в спор. Ведь ничего нельзя доводить до крайности, в том числе и идею, что крайние идеи не бывают правильными. Здесь, по-моему, как раз такой случай. Я поддерживаю крайнюю идею, что goto в современных ООП-языках не нужен.

Алексей Полушин[досье] Отличная мысль :)

спустя 19 дней [обр] Василий Свиридов(53/175)[досье]

goto-срач переполз на хабр :)

http://habrahabr.ru/blogs/php/62863/

Powered by POEM™ Engine Copyright © 2002-2005