AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 157

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

            Но на вкус и цвет…
      +3
      Неплохо было бы также дать линк на оригинал: xkcd
        0
        А так же на перевод :)
          0
          Добавил и то и то.
        • UFO just landed and posted this here
        • UFO just landed and posted this here
            +5
            jz и аналоги — это не goto, это if

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

            А для высокоуровневых языков, goto — это действительно плохо, особенно если учесть, что возможны множественные точки выхода у функций.
            • UFO just landed and posted this here
                0
                Goto у языков разные. Во многих (PHP в их числе) на уровень ниже (внутрь функции, цикла) переходить нельзя.
                  0
                  Тогда он вообще теряет смысл.
                  +3
                  если писать на чистом 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ов
                    +1
                    Чистый С по современным меркам — язык низкого уровня.
                      +3
                      Конечно правильнов С использовать goto в таких случаях, ведь изначально С был задуман как красивый ассемблер.
                        +2
                        if (! f ) {
                        perror(«fopen»);
                        }
                        else if ( rand() > 5 ) {
                        result = 1;
                        }
                        else if ( rand() > 10 ) {
                        result = 2;
                        }
                        else {
                        result = 3
                        }

                        не красиво?
                          +5
                          в предыдущем было все же читабельнее за счет того, что видно было — сразу идем на выход.
                          0
                          на ЯВУ такое реализуется через try… finally, причем гораздо понятнее реализуется
                            +2
                            просто в С нет исключений :)
                              –1
                              Можно и без кучи 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. }
                                0
                                я показал в примере очень простую функцию, если же функция сложная, с кучей вложенных while/for/switch то данный трюк не проходит
                                  +2
                                  >если же функция сложная, с кучей вложенных while/for/switch то....

                                  … она требует рефакторинга ;)
                              • UFO just landed and posted this here
                              • UFO just landed and posted this here
                                –2
                                Если имеется обширный опыт программирования, то можно пожалуйста увидеть код, который с goto, будет выглядеть, красиво и лаконично. И в который не надо будет всматриваться десять минут?
                                  +1
                                  <?php
                                  begin:
                                    echo $i++;
                                  goto begin;


                                  * This source code was highlighted with Source Code Highlighter.
                                    –1
                                    Смешно. А что-нибудь реальное?
                                    • UFO just landed and posted this here
                                        0
                                        А причем тут асм, если речь в данном топике о php?
                                          +28
                                          И часто вы php-код компилируете?
                                            +1
                                            Не поверите — каждый раз перед выполнением :)
                                            Если кэш опкода не подключен, конечно.
                                              0
                                              Бывает и по тысячи раз в день выходит. Да и при чем тут компиляция пыха и goto?
                                          –6
                                          for(int i = 0; i < arrayLength; ++i)
                                          {
                                              if (array[i] == 5) goto FOUND;
                                          }
                                          // doing somthing
                                          return false;
                                          FOUND:
                                          // doing somthing else
                                          return true;
                                          
                                            –3
                                            Конечно же, в жтом сулчае можно было обойтись флажком, например. В операторе гоуту нет ничего плохого, если использовать его с головой а не пихать везде подряд. И, опять же, если он такой плохой, почему этот оператор есть почти во всех языках?
                                              +4
                                              в этом случае даже без флага можно, т.к. у вас return все равно
                                              for(int i = 0; i < arrayLength; ++i) 
                                              {
                                                  if (array[i] == 5) {//found
                                                      // doing somthing else
                                                      return true;
                                                  }
                                              }
                                              //not found
                                              // doing somthing
                                              return false;
                                              
                                                +2
                                                Я лишь привел пример поиска. Ситуации, когда 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 нет.
                                                  +4
                                                  >Но иногда возникают ситуации, когда другие решения являются менее красивыми.
                                                  Спасибо, поржал. Попросили привести реальный код, когда это оправдано, вы привели говнокод, сказали, что это говнокод и сказали, что есть ситуации. Вас снова попросили. Вы снова привели говнокод и снова сказали, что есть ситауции. Так приведите же, наконец, саму ситуацию, а не говнокод и надпись, что ситуация есть!
                                                    +1
                                                    Рад, что мне удалось поднять вам настроение.
                                                    0
                                                    Если нигде не ошибся, то вроде тоже самое будет:
                                                    if (!condition) {
                                                    // some code here
                                                    if (!another_condition) {
                                                    //some another code here
                                                    return true;
                                                    }
                                                    }
                                                    //some cleanup code
                                                    return false;
                                                      +1
                                                      Ой сорри:
                                                      if (!condition) {
                                                          // some code here
                                                          if (!another_condition) {
                                                              //some another code
                                                              return true;
                                                          }
                                                      }
                                                      //some cleanup code here
                                                      return false;
                                                      
                                                        0
                                                        теперь пердположим, что кондишенов пять

                                                        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;
                                                        


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

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

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

                                                                if(func2())
                                                                break;

                                                                if(func3())
                                                                break;

                                                                if(func4())
                                                                break;

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

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

                                                                Ваши предложения по рефакторингу?
                                                                  0
                                                                  В данном случае я не вижу особой разницы между goto и do-while, если честно.
                                                                  Однако, я соглашусь, что goto, модет быть полезен, НО там где не хватает других средств языка.
                                                                  В основном это будут низкоуровневые вещи (об асме ниже уже вспомнили).
                                                                  +4
                                                                  Вот пример из 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;
                                                                  }
                                                                  
                                                                    0
                                                                    согласен, ответил чуть выше.
                                                                    –2
                                                                    Вот кусок кода под действием предрассудков 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.
                                                                    +1
                                                                    if(!condition && !another_condition && !another_condition && !another_condition) {
                                                                      return true;
                                                                    } else {
                                                                      return false;
                                                                    }
                                                                    


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

                                                                      // some code here

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

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

                                                                        может быть и

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

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

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

                                                                        потому как иногда условия могут и по несольку строчек быть.
                                                                  +1
                                                                  особые извращенцы в страхе 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.
                                                                    0
                                                                    >особые извращенцы в страхе goto пишут так (и считают это хорошим стилем):

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                                                                                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;
                                                                                    ...
                                                                                  }
                                                                                 }
                                                                                
                                                                                  +1
                                                                                  Ну что ж, здесь я сдаюсь. Чудес не бывает. Приведённый Вами код и есть лучшее, что можно сделать без goto. Но красивее и лаконичнее ли он моего? На мой взгляд — нет. Мне кажется, goto для выхода из двойного цикла читается лучше этого варианта с флагом. А главное (!) зачем? Только ради того, чтобы избавиться от «неправильного» оператора.
                                                                                    0
                                                                                    Да я не спорю, просто делюсь опытом. Для меня, мой метод — это стандарт. Работает во всех почти во языках.

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

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

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


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

                                                                                  А для PHP — это зло
                                                                                    –2
                                                                                    Что же тогда сказать о PHP-GTK?
                                                                                      +8
                                                                                      кошмар
                                                                                    –13
                                                                                    А я за goto. Фильтровать быдлокодеров.
                                                                                    Открыл код, увидел goto, послал нах. Если конечно знаешь, как сделать без goto.
                                                                                    • UFO just landed and posted this here
                                                                                        +23
                                                                                        возможно, предложение не согласовано :))
                                                                                        (с) Майкрософт Ворд
                                                                                          0
                                                                                          человек пошутил, а вы его заминусовали:) лично мне его сарказм понравился:)
                                                                                            0
                                                                                            человек пошутил, а вы его заминусовали:) лично мне его сарказм понравился:)
                                                                                              0
                                                                                              сорри за второй коммент — видимо из-за связи!
                                                                                            +1
                                                                                            Помню где-то раздобыли часть исходников виндовса, в которых я нашел строку «goto vpeezdoo»
                                                                                              +12

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


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

                                                                                              © ##php @ irc.freenode.net, только что
                                                                                                +7
                                                                                                Для выхода из нескольких вложенных циклов считаю вполне допустимым использовать goto.
                                                                                                  +10
                                                                                                  О, догматики уже минусов понаставили :-)
                                                                                                  Использование 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).
                                                                                                    +6
                                                                                                    Эм… Возможно, что я не понял вашей великой мысли… Но нельзя ли в вашем примере, переписанном на PHP (ведь мы сейчас о нем говорим, да?), просто использовать циферки, соответствующие вложенности? Навроде этого:

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

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

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

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

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

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

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

                                                                                                                  P.S. Как никак, без goto уже обхожусь 3 года. Вспоминаю страшные программы однокурсников по паскалю, где этих goto было не счесть.
                                                                                                                  • UFO just landed and posted this here
                                                                                                                      +2
                                                                                                                      Эх, молодость, ZX Spectrum :)
                                                                                                                      0
                                                                                                                      Holy war never changes…
                                                                                                                        +4
                                                                                                                        Вот хаете тут, а никто даже не посмотрел или не упомянул, что goto в PHP имеет следующие ограничения:

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

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

                                                                                                                                  Only users with full accounts can post comments. Log in, please.