Как стать автором
Обновить

GOTO

Время на прочтение1 мин
Количество просмотров8.9K
Всего голосов 107: ↑77 и ↓30+47
Комментарии157

Комментарии 157

Neal Stephenson thinks it's cute to name his labels 'dengo'
Goto Dengo :)
Криптономикон — это очень хорошая книга :)
Нил Стивенсон — это очень клевый автор.
Раз уж про Нила, то Криптономикон действительно так крут? Просто Лавина мне показалась полной фигнёй.
Это принципиально разные книжки. На мой взгляд Криптономикон гораздо интереснее. К тому же он жизненнее и в его основе лежат вполне конкретные исторические персонажи.

Но на вкус и цвет…
Неплохо было бы также дать линк на оригинал: xkcd
А так же на перевод :)
Добавил и то и то.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
jz и аналоги — это не goto, это if

goto — это только jmp и (внимание!) call. Отличие последней в том, что по возможен возврат на точку, откуда тебя послали.

А для высокоуровневых языков, goto — это действительно плохо, особенно если учесть, что возможны множественные точки выхода у функций.
НЛО прилетело и опубликовало эту надпись здесь
Goto у языков разные. Во многих (PHP в их числе) на уровень ниже (внутрь функции, цикла) переходить нельзя.
Тогда он вообще теряет смысл.
если писать на чистом C (особенно для какой нибудь мелкой железки) то удобно оформлять функцию в виде

int foo()
{
  FILE f = NULL;
  int result = 0 ;
  f = fopen("somefile.txt", "r");
  if ( ! f ) {
    perror("fopen");
    goto exit;
  }
  
  if ( rand() > 5 ) {
    result = 1;
    goto exit;
  }

  if ( rand() > 10 ) {
    result = 2;
    goto exit;
  }

  result = 3

exit:
  if (f)
    fclose(f);

  return result;
}


имхо это читабельней чем городить кучу вложенных ifов
Чистый С по современным меркам — язык низкого уровня.
Конечно правильнов С использовать goto в таких случаях, ведь изначально С был задуман как красивый ассемблер.
if (! f ) {
perror(«fopen»);
}
else if ( rand() > 5 ) {
result = 1;
}
else if ( rand() > 10 ) {
result = 2;
}
else {
result = 3
}

не красиво?
в предыдущем было все же читабельнее за счет того, что видно было — сразу идем на выход.
на ЯВУ такое реализуется через try… finally, причем гораздо понятнее реализуется
просто в С нет исключений :)
Можно и без кучи if-ов и без goto ;)

  1. int foo()
  2. {
  3.   FILE f = NULL;
  4.   int result = ;
  5.   f = fopen("somefile.txt", "r");
  6.  
  7.   do {
  8.     if ( ! f ) {
  9.       perror("fopen");
  10.       break;
  11.     }
  12.  
  13.     if ( rand() > 5 ) {
  14.       result = 1;
  15.       break;
  16.     }
  17.  
  18.     if ( rand() > 10 ) {
  19.       result = 2;
  20.       break;
  21.     }
  22.  
  23.     result = 3
  24.  
  25.   } while (false);
  26.  
  27.   if (f)
  28.     fclose(f);
  29.  
  30.   return result;
  31. }
я показал в примере очень простую функцию, если же функция сложная, с кучей вложенных while/for/switch то данный трюк не проходит
>если же функция сложная, с кучей вложенных while/for/switch то....

… она требует рефакторинга ;)
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Если имеется обширный опыт программирования, то можно пожалуйста увидеть код, который с goto, будет выглядеть, красиво и лаконично. И в который не надо будет всматриваться десять минут?
<?php
begin:
  echo $i++;
goto begin;


* This source code was highlighted with Source Code Highlighter.
Смешно. А что-нибудь реальное?
НЛО прилетело и опубликовало эту надпись здесь
А причем тут асм, если речь в данном топике о php?
И часто вы php-код компилируете?
Не поверите — каждый раз перед выполнением :)
Если кэш опкода не подключен, конечно.
Бывает и по тысячи раз в день выходит. Да и при чем тут компиляция пыха и goto?
for(int i = 0; i < arrayLength; ++i)
{
    if (array[i] == 5) goto FOUND;
}
// doing somthing
return false;
FOUND:
// doing somthing else
return true;
Конечно же, в жтом сулчае можно было обойтись флажком, например. В операторе гоуту нет ничего плохого, если использовать его с головой а не пихать везде подряд. И, опять же, если он такой плохой, почему этот оператор есть почти во всех языках?
в этом случае даже без флага можно, т.к. у вас return все равно
for(int i = 0; i < arrayLength; ++i) 
{
    if (array[i] == 5) {//found
        // doing somthing else
        return true;
    }
}
//not found
// doing somthing
return false;
Я лишь привел пример поиска. Ситуации, когда goto делает куд читабельнее и красивее есть. И поиск — это одина из вероятных ситуаций.

if (condition)
{
   goto CANCEL;
}
// some code here
if (another_condition)
{
    goto CANCEL;
}
// some another code here
return true;

CANCEL:
// some cleanup code
return false;


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

Нет ничего плохого в том, чтоб грамотно использовать goto. Я не сую его во все щели и мало того, в python, на котором я очень люблю писат оператора goto нет.
>Но иногда возникают ситуации, когда другие решения являются менее красивыми.
Спасибо, поржал. Попросили привести реальный код, когда это оправдано, вы привели говнокод, сказали, что это говнокод и сказали, что есть ситуации. Вас снова попросили. Вы снова привели говнокод и снова сказали, что есть ситауции. Так приведите же, наконец, саму ситуацию, а не говнокод и надпись, что ситуация есть!
Рад, что мне удалось поднять вам настроение.
Если нигде не ошибся, то вроде тоже самое будет:
if (!condition) {
// some code here
if (!another_condition) {
//some another code here
return true;
}
}
//some cleanup code
return false;
Ой сорри:
if (!condition) {
    // some code here
    if (!another_condition) {
        //some another code
        return true;
    }
}
//some cleanup code here
return false;
теперь пердположим, что кондишенов пять

if (!condition) 
{
    // some code here
    if (!another_condition) 
    {
        //some another code
        if (!another_condition) 
        {
            //some another code 
            if (!another_condition) 
            {
                //some another code 
                if (!another_condition) 
                {
                    //some another code 
                    return true;
                }
            }
        }
    }
}
//some cleanup code here
return false;


так?
Формально — да.
Только это все абстрактные куски кода.
Привидите реальный пример где у вас тру возвращается только при верности 5 условий, на каждое условие вы выполняете код, а клин делаете не зависимо от сочетания условий.
Я почти уверен, что в таком случае надо рефакторить.
Что-то у меня с русским не то =)
Вы когда нить писали на чистом С? Знаете, там нет исключений.

А теперь представьте себе код, который вызывает подряд n функций, каждая из которых может вернуть ошибку. Если возникла ошибка — мы прерываем выполнение кода и делаем какую-нить очистку.

В результате у нас код выглядит приблизительно вот так:
//malloc чего-нить
do
{
if(func1())
break;

if(func2())
break;

if(func3())
break;

if(func4())
break;

}while(0)
//free чего-нить
Используется do{}while(0) только из-за предубежденности против goto. Хотя данная конструкция ничем не лучше (а может даже хуже) чем goto.

Это почти реальный код для микроконтроллера. Логика парсинга пакетов и проведения платежей на POS-терминале.
Размер памяти кода ограничен, размер оперативной памяти ограничен.

Ваши предложения по рефакторингу?
В данном случае я не вижу особой разницы между goto и do-while, если честно.
Однако, я соглашусь, что goto, модет быть полезен, НО там где не хватает других средств языка.
В основном это будут низкоуровневые вещи (об асме ниже уже вспомнили).
Вот пример из linux:

int p54_read_eeprom(struct ieee80211_hw *dev)
{
        struct p54_common *priv = dev->priv;
        struct p54_eeprom_lm86 *eeprom_hdr;
        struct sk_buff *skb;
        size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize;
        int ret = -ENOMEM;
        void *eeprom = NULL;

        maxblocksize = EEPROM_READBACK_LEN;
        if (priv->fw_var >= 0x509)
                maxblocksize -= 0xc;
        else
                maxblocksize -= 0x4;

        skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(*eeprom_hdr) +
                            maxblocksize, P54_CONTROL_TYPE_EEPROM_READBACK,
                            GFP_KERNEL);
        if (!skb)
                goto free;
        priv->eeprom = kzalloc(EEPROM_READBACK_LEN, GFP_KERNEL);
        if (!priv->eeprom)
                goto free;
        eeprom = kzalloc(eeprom_size, GFP_KERNEL);
        if (!eeprom)
                goto free;
...
еще пол экрана кода
...
        ret = p54_parse_eeprom(dev, eeprom, offset);
free:
        kfree(priv->eeprom);
        priv->eeprom = NULL;
        p54_free_skb(dev, skb);
        kfree(eeprom);

        return ret;
}
согласен, ответил чуть выше.
Вот кусок кода под действием предрассудков goto

function _functiob( Url: PAnsiChar; var OutBuf: PAnsiChar ): Boolean;
const
UrlExpr: PAnsiChar = '(http://)?([^/]+)(.+)';
HeaderTpl: PAnsiChar = 'GET ${3} HTTP/1.0'#13#10'Host: ${2}'#13#10'Connection: Close'#13#10#13#10;
var
S: TSocket;
R: HRegExp;
Cnt: Integer;
Buf: PAnsiChar;
BufLen, ResLen: Cardinal;
begin
OutBuf := Nil;
Result := False;
if ( Url = nil ) or ( RegComp ( UrlExpr, R ) <> RE_OK ) then
Exit;
S := INVALID_SOCKET;

try
if not RegExec( R, Url ) then
Exit;
Buf := RegMatchStr( R, 2 );
if (Buf = nil) then Exit;
S := CreateSocketAndConnect( Buf );
StrDispose( buf );
if ( S = INVALID_SOCKET ) then
Exit;

Buf := StrNew(Url);
BufLen := StrLen(Buf);
RegReplace(UrlExpr, HeaderTpl, Buf, BufLen, 1);
if (not SendSocketData(S, Buf, BufLen)) then
Exit;

ResLen := 0;
OutBuf := Nil;
BufLen := StrBufSize(Buf);
repeat
Cnt := Recv( S, Buf^, BufLen, 0 );
if Cnt > 0 then
CollectBuf(Buf^, OutBuf, ResLen, Cnt);
until (Cnt <= 0);

If (GetHTTPAnsvNFromHeader(OutBuf) <> 200) then
Exit;

BufLen := GetHeaderSize( OutBuf );
if (BufLen = 0) then Exit;

Dec ( ResLen, BufLen );
Move ( OutBuf[BufLen], OutBuf^, ResLen );

StrRealloc(OutBuf, ResLen + 1);
OutBuf[ResLen] := #0;
Result := True;
finally
if (Buf <> Nil) then StrDispose(Buf);
if (not Result) and ( OutBuf <> Nil ) then
begin
StrDispose(OutBuf);
OutBuf := Nil;
end;
if (S <> INVALID_SOCKET) then
CloseSocket( S );
RegFree( R );
end;
end;

Try..Finally+ Exit внутри блока вместо goto.
if(!condition && !another_condition && !another_condition && !another_condition) {
  return true;
} else {
  return false;
}


А может так? :)
только там еще есть

// some code here

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

if(condition) {
  // кусок кода, который зависит от условия
  // и вызывает преждевременную остановку программы
  goto CANCEL;
}

может быть и

if(condition) {
  // кусок кода, который зависит от условия
  // но не вызывает преждевременную остановку программы
}
Все верно. Я просто не исключаю случаи, когда оператор goto становится полезным, мало того, я иногда его использую.

Мне не по душе крики о том, что использование оператора goto — это удел красноглазиков. Это и пытался донести.
тогда уж лучше сделать что-то вроде:
if(checkConditions()) {
} else {
}

а в чек кондишнс можно уже и написать что-то вроде
return checkFirstCondotion() && checkSecondCondition() && ...;

потому как иногда условия могут и по несольку строчек быть.
особые извращенцы в страхе goto пишут так (и считают это хорошим стилем):
do {
if (condition)
break;

// some code here
if (another_condition)
break;

// some another code here
return true;

} while (0);

// some cleanup code
return false;

Вот по-моему уж лучше goto.
>особые извращенцы в страхе goto пишут так (и считают это хорошим стилем):

Вот по-моему уж лучше goto.


Вы не поверите, но это не просто «считается» — это и есть хороший стиль, и мифический «страх goto» тут не при чём.
Когда читаешь код, то при использовании конструкции «do {...} while(0);» найти «точку выхода» гораздо легче, потому что она в заранее известном месте: в конце блока. При использовании goto выход может оказаться где угодно.
Простите, а как же семантика?

Любой, кто видит конструкцию «do {...», начинает сначала вдумываться зачем тут нужен цикл, и только потом, в конце, обнаруживает "} while(0);". Это может сильно путать.

Иными словами, do… while предназначено для другого, а именно — для циклов с постусловием. И с точки зрения семантики для других целей эта конструкция не применима.
Если выбирать между 100%-верной и правильной семантикой с одной стороны и читабельностью кода с другой стороны — лично я выберу второе.

Можно сколь угодно долго теоретизировать над семантикой, но в «полевом» применении код с «do {...} while(0);» читается и сопровождается намного легче — это факт.

А уж если рассуждать с точки зрения семантики и возводить всё в абсолют, то конструкция for(;;) тоже неприменима: оператор for предназначен для другого, а именно — для цикла с первичной инициализацией, условием и выполнением оператора после каждой итерации. А для бесконечного цикла надо использовать while(true). Верно? ;)
> лично я выберу второе.

я не знаю ни одного примера, когда следование правилам семантики вредит читаемости кода. и наоборот, отступление от семантического порядка — всегда вредит.

>читается и сопровождается намного легче — это факт

все же — не факт. сильно запутывает, когда для решения одних задач используются конструкции, предназначенные для других задач (то есть когда нарушается семантика, не спроста же она придумана).

> А для бесконечного цикла надо использовать while(true). Верно?

while(true) действительно несколько более предпочтительно. гикам нравится использовать for(;;) только потому, что это на несколько символов короче.

но нужно помнить, что с точки зрения семантики while(true) — все равно не идеально, так как это цикл с предусловием, которого в случае вечного цикла получается что нет.

то есть с точки зрения семантики было бы логично ввести специальную конструкцию для вечных циклов, скажем, loop {… }.

но этого нет и не будет, потому что, помимо всего прочего, в идеале, вечных циклов в реальных программных продуктах вообще не должно быть (тема для нового холивара?), но это уже другая тема…
>я не знаю ни одного примера, когда следование правилам семантики вредит читаемости кода. и наоборот, отступление от семантического порядка — всегда вредит.

Т.е. текущий пример с goto Вам не нравится?

Вы отойдите от теории и спуститесь на землю: вот читаю я чей-то код, тут мне попадается «goto some_label;» — и где я её должен искать? Запускать поиск? Скроллить и пытаться поймать глазами? И хрен с ним, что неудобно искать — зато, панимашь, семантически верно, да?
А вот если стоит do {...} while(false), то я знаю наверняка, куда мы попадём после break: в конец блока, который видно даже невооружённым беглым взглядом, кинутым по диагонали. Будете спорить?

Может быть, всё же стоит убавить градус категоричности в своих заявлениях?
>> А вот если стоит do {...} while(false), то я знаю наверняка, куда мы попадём после break: в конец блока, который видно даже невооружённым беглым взглядом, кинутым по диагонали.

Как метка так и конец блока могут как быть так и не быть в пределах досягаемости беглого взгляда. Метка хороша тем, что это не какая-то безликая скобочка и ее можно найти поиском. И она не уйдет со своего места, если кто-нибудь захочет поместить внутрь do {} while(0) вложенный цикл, по случаю охватывающий и ваш break.
>Как метка так и конец блока могут как быть так и не быть в пределах досягаемости беглого взгляда.

При скролле глаз цепляется за изменение уровня вложенности куда легче, чем за текстовую метку.

>И она не уйдет со своего места, если кто-нибудь захочет поместить внутрь do {} while(0) вложенный цикл, по случаю охватывающий и ваш break.

Вдруг откуда ни возьмись случайно взялся вложенный цикл? :)
Ну извините, тут мне действительно нечего возразить…

В общем, я свои аргументы привёл, а уж решать, весомые они или нет — личное дело каждого.
for(;;)
{
echo $i++;
}
while(1)
{
echo $i++
}

вопрос стилевых предпочтений.

я предпочитаю кодировать infinite loop как for(;;).
while(1) это классический пример бесконечного цикла

Хотя кому как больше нравится ;)
Такая конструкция в некоторых языках вызывает warning, поэтому обычно пишут все-таки for (;;) { }
И часто Вам приходится кодировать infinite loop?:)
Как ни странно, но приходилось. =) Давно это было и не правда. Даже не помню зачем.
проверить таймаут скрипта :)
приём системных сообщений в win проге или принимающего секета.
Для демонов различного рода достаточно обычный код.
Спасибо. Я сам не додумался чего-то. Возможно для вечно работающих сервисов — самое оно.
Хотя звучит как-то все равно коряво. Ведь должны же быть какие-то возможность остановки. Т.е. нужно в цикл этот передать событие, которые остановит этот цикл.
Думаю, что для этого конструкция for(;;) врядли подойдет — вот while(boolen) как-то красивее смотрится…
for (;; print($i++)) {}
for (int y=0;;printf("%d", ++y));
или
for (int y=0;printf("%d", ++y););
я фигею, дорогая редакция:)
тогда уж
for (;; print($i++)) ;

но нафик-нафик такие «оптимизации» )))
while(print $i++);
Классика:

for(int i = 0; i < M; ++i)
for(int j = 0; j < N; ++j)
{
do_something();
if(some_condition())
goto exit;
}
exit:;

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

в вашем случае вместо goto exit — return; потому что код внутри метода.
понадобился goto внутри одного метода? — рефакторинг.
Я вот что думаю: никто же не говорит, что break (AKA exit for) — это плохо. Есть такое понятие (чисто концептуально): выход из цикла. Так уж сложилось, что традиционные языки вроде С++ поддерживают выход из цикла только на один уровень вверх (ниже пишут, что в Javascript и РНР можно и на два уровня).

Возможно, здесь можно выделить метод, сделать рефакторинг и т.п., но не будем заставлять телегу бежать впереди лошади. Предположим, у меня есть алгоритм с циклом посередине. Я не хочу рефакторинга, пусть будет в одной процедуре. Из цикла выходим с помощью break. Теперь у меня есть вложенный цикл. По сути это то же самое — цикл + выход из него. Здесь нужно делать реорганизацию кода лишь из-за того, что язык не позволяет выйти из вложенного цикла?! :)
Вы правильный вопрос задали, как я выше написал — мы на грани холивара. :)
return из inline функций, тоже можно расценивать как goto :)

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

на самом деле, я считаю, что вопрос использовать goto или нет — в основном (но не только), удобство работы в команде, т.е. читаемость Вашего кода другими разработчиками, без Вашего участия. если не использовать «goto vpizdu», т.е. не всегда очевидно куда :), возможно такие конструкции бывают понятны и уместны, но, как видно из практики вообще и из этого топика в частности, большинство разработчиков goto воспринимают негативно.

ps: например, мне за ~8 лет работы ни разу не пришлось/захотелось написать goto, хотя, возможно, это мои предрассудки.
Да, холивар — штука опасная :) В принципе, конечно, главное — читабельность. В конце концов, если Вам не нравится goto, сделаете рефакторинг, но код с выходом за пределы двойного цикла тоже понятен сразу — и даже если Вы сами его не пишете, другого поймёте.

А методологии… ээх, в большинстве учебников по С++ сейчас пишут: нигде и никогда не используйте препроцессор! При этом открываешь boost, и видишь, что половина его написана на чистом препроцессоре :)
в ситуации с выходом из двойного цикла, я подозреваю, проблема в двойном цикле, хотя, опять же, возможно, я просто не сталкивался с нужной для такого решения задачей.
Не знаю, красиво это, или некрасиво, я в таких случаях всегда выставляю флаг. Его еще можно как-нибудь понятно назвать.
Ну так приведите код — подозреваю, будет неприятная бодяга с двумя break-ами.
Что-то типа такого:
exit_flag = False
while(!exit_flag) {
    while(!exit_flag) {
     ....
     exit_flag = True;
     break;
     ....
    }
}
Да, но у вас пропал цикл с перебором i и j. Если их добавить, получится куда грустнее и объемнее.
Вообще-то я всегда ставил строчку:

for(...
    if(!exit_flag) { break; }


Но вот буквально сейчас подумал, что ведь наверное можно и так:

exit_flag = False;
for(i=0;i++;i<10 && !exit_flag) {
  if(!exit_flag) { break; }
  for(j=0;j++;j<10 && !exit_flag) {
    ...
    exit_flag = True;
    ...
  }
 }
Ну что ж, здесь я сдаюсь. Чудес не бывает. Приведённый Вами код и есть лучшее, что можно сделать без goto. Но красивее и лаконичнее ли он моего? На мой взгляд — нет. Мне кажется, goto для выхода из двойного цикла читается лучше этого варианта с флагом. А главное (!) зачем? Только ради того, чтобы избавиться от «неправильного» оператора.
Да я не спорю, просто делюсь опытом. Для меня, мой метод — это стандарт. Работает во всех почти во языках.

А goto я не применяю. В сложных случаях я всегда применяю флаги с читабельными названиями.

Цель — максимально повысить читабельность кода. На мой взгляд в последнем примере хорошо то, что в строке for сразу и в одном месте видны все условия, по которым производится выход из этого цикла.
Приношу извинения. Забыл убрать строчку с if(), в предыдущем сообщении следует читать:

exit_flag = False;
for(i=0;i++;i<10 && !exit_flag) {
  for(j=0;j++;j<10 && !exit_flag) {
    ...
    exit_flag = True;
    ...
  }
 }
А если внутри первого цикла есть какой-то код, выполняющийся после тела второго цикла, то в случае «моментального выпрыгивания» он не выполнится, а в Вашем случае — выполнится ;)
Конечно, только это ни хорошо и ни плохо. Это должен предусмотреть программист.
Добавил: Причем break нужен только тогда, если хотим, чтобы операторы после выставления флага не выполнялись. Обычно можно совсем без брейков.
break 2
очевидно, что меньшая часть языков поддерживает такое.
мы с Вами в блоге PHP, верно?
Если бы вы знали язык на котором пишете, то наверняка бы вспомнили, что есть такая чтука как break, которой можно указать сколько цикцлов или структур switch, из которых надо выйти:

for($i = 0; $i < 10; $i++) {
    for($j = 0; $j < 10; $j++) {
        $result = $i*10 + $j;
        var_dump($result);
        if($result == rand(0, 99)) {
            break 2;
        }
    }
}



Почитайте доки, они полезны.
Я не пишу на РНР — мне кажется, данная ветка обсуждения уже слегка выходит за пределы конкретных языков. Да, в РНР можно так, но мало где ещё можно.
Не вижу чем это лучше GOTO при выходе из двойного цикла? А если тройной и т.п.? Когда читаю ваш код, я буду отсчитывать два цикла назад, искать конец блока внешнего цикла. Здесь конечно всё очевидно, но бывает куда больше строк кода в обоих циклах, что можно сильно запутаться. А тут раз и условие, переходим в метку и читаем код дальше. Согласен, что этот пример куда лучше чем с флагами, но всё-же.
Полуркай linux kernel
Странно, что на динозавре нет наездника-нациста.
В asm без goto будет тяжело ;)

А для PHP — это зло
Что же тогда сказать о PHP-GTK?
кошмар
А я за goto. Фильтровать быдлокодеров.
Открыл код, увидел goto, послал нах. Если конечно знаешь, как сделать без goto.
НЛО прилетело и опубликовало эту надпись здесь
возможно, предложение не согласовано :))
(с) Майкрософт Ворд
человек пошутил, а вы его заминусовали:) лично мне его сарказм понравился:)
человек пошутил, а вы его заминусовали:) лично мне его сарказм понравился:)
сорри за второй коммент — видимо из-за связи!
Помню где-то раздобыли часть исходников виндовса, в которых я нашел строку «goto vpeezdoo»

if((ArrCharDead[i].keyindex == index) && (ArrCharDead[i].numdead == ActiveDead))
goto vpizdu;


исходники
это шутка? чья?
<+cyth> loonysalmon, here is the rule, if you have to ask about goto, forget it exists

© ##php @ irc.freenode.net, только что
Для выхода из нескольких вложенных циклов считаю вполне допустимым использовать goto.
О, догматики уже минусов понаставили :-)
Использование goto для выхода из нескольких вложенных циклов — нормальная практика.
stackoverflow.com/questions/324831/breaking-out-of-a-nested-loop

Нельзя догматично отвергать goto. Этот оператор есть во всех языках, где он нужен.
Надо просто понимать, в каких (редких) случаях стоит его использовать.
Дональд Кнут целую большую статью написал по этому поводу. Догматикам советую почитать на досуге для развития способности критически мыслить: http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf (PDF).
Эм… Возможно, что я не понял вашей великой мысли… Но нельзя ли в вашем примере, переписанном на PHP (ведь мы сейчас о нем говорим, да?), просто использовать циферки, соответствующие вложенности? Навроде этого:

while(true) {
while(true) {
break 2;
}
}

А вообще по теме — кто захочет написать код, в котором невозможно разобраться, у того это получится и без goto :-)
Ну тут уже дискуссия не только про PHP пошла.
А про break «levels» в PHP не знал, каюсь :-) Ибо не использую PHP практически.
break 2 это ещё большее зло, чем goto наружу цикла. Программист не обязян уметь считать уровни вложенности, к тому же при рефакторинге их количество может измениться.

Более-менее правильно сделано в жаваскрипте:
top:
while(true) {
  while(true) {
    break top;
  }
}
программист «не обязан»… ну-ну =)
продолжая мысль о необязательности уметь считать уровни вложенности — «Программист не обязан знать чего делает его код» =))
Подумалось… Вот именно в такой ситуации, break N ещё более великое зло, чем goto.

Объясняю: если указан goto somewhere, то вне зависимости от дальнейших модификаций кода, goto somewhere будет выходить именно на somewhere, а не куда-то ещё.

А вот break N в случае добавления/убирания циклов будет выкидывать не туда, куда надо, и такую ошибку очень легко допустить, особенно если код циклов достаточно большой, а не три строчки как в вышеприведённых примерах.

Так что в плане дальнейшей поддержки кода goto выглядит привлекательнее, чем break N.

Хотя лично сам goto в php никогда не использовал и не имел даже такого побуждения. Как-то код всегда рефакторился в удобочитаемый вид без подобных выкрутасов.
в php есть goto? :-)
5.3
Зачем они его добавили, они мотивировали? :)
Видимо у них есть отличный план. Чего только стоит их предыдущий перл про выбор названия для "::" (двойного двоеточия):
«Paamayim Nekudotayim» на первый взгляд может показаться странным словосочетанием для обозначения двойного двоеточия. Однако, во время создания Zend Engine версии 0.5 (который входил в PHP3), Andi и Zeev выбрали именно это обозначение. «Paamayim Nekudotayim» действительно значит «двойное двоеточие». На иврите. Просто это обозначение не менялось ни разу в течение всего времени разработки PHP.
НЛО прилетело и опубликовало эту надпись здесь
Не чоень понятно, при чём тут вообще PHP и создатели его документации :)
это все питонисты и рубисты завидуют, у них то goto нет!
А ещё там нет «break 2»
в питоне есть, но в виде шутки. entrian.com/goto/
Предостережение вверху статьи радует:)
Покормить тролля?
Вспомнился случай с первого курса:
Нам читали С. Чувак намутил прогу, а там GOTO. Препод говорит: плохой стиль, перепеши — тогда я приму. А он в программировании null (как и преподша вообщем). Он взял и табом позаганял метки за пределы экрана, и к преподше… Зачет.
ЗЫ. Преподшу поменяли только год назад, это через 6 лет после того случая. Весь факультет знал, что она тупая.
=D У нас многие так угарали =) всё что мешало загоняли далеко…
метод последовательных табуляций
Ну вот, зачем сказали, что он там теперь есть? Я расстроен.
В чём причина вашего расстройства? Вас не печалит, что goto есть в Си?
В Си меня все устраивает, даже больше, чем.
А вот от ПХПпистов не ожидал… злого break и так хватало…
Что-то мне уже давно не приходилось видится с goto, с тех пор как освоил ООП и структурное программирование. Да и необходимости даже не было.

P.S. Как никак, без goto уже обхожусь 3 года. Вспоминаю страшные программы однокурсников по паскалю, где этих goto было не счесть.
НЛО прилетело и опубликовало эту надпись здесь
Эх, молодость, ZX Spectrum :)
Holy war never changes…
Вот хаете тут, а никто даже не посмотрел или не упомянул, что goto в PHP имеет следующие ограничения:

1). Нельзя выпрыгнуть за пределы цикла и case'ов.
2). Возвращатся НЕЛЬЗЯ, т.е. перейти на метку можно только вперёд по потоку выполнения программы. Т.е. бесконечные циклы с помощью goto — забудте.
1) Тогда смысла в нем вообще нет — из двойного цикла не выйти. Только добавит в код макарон.
А выход есть — через break(2) ;)
GOTO снова в моде :-)
Все новое — хорошо забытое старое.
Исходники ядра linux не хило нашпингованы оперетором goto
О-о, холивар такой холивар :)
НЛО прилетело и опубликовало эту надпись здесь
В php достаточно языковых конструкций для того чтобы полностью исключить использование оператора goto, и все слюнопускательства по поводу «а вот в ассемблере, а вот в си, а вот в...» — пустая болтология, вот пусть в языках где единственная возможность выйти из вложенного цикла — это goto — его и вводят, благо в php такая возможность есть и без goto, а еще функции/методы, исключения и иже с ними, которые все вместе с лихвой покрывают необходимость в goto.
Плюс один. Зато у говнокодеров появится ещё больше возможностей испортить код, а у критиков — попенять на то, что php-шники не умеют нормально программировать.

Нормальные языки _помогают_ писать хорошие программы, а PHP своей бездарной архитектурой провоцирует писать говнокод… Только теперь он будет банановый — с goto.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории