LINUX.ORG.RU

do{} while(0) вместо вложенных ифов

 ,


2

4

Привет!
Народ, откуда пошла такая конструкция?

do
{
 if ( !cond0 ) break;
 foo();
 if ( !cond1) break;
 bar();
 //...
 if ( !condN) break;
return true;
} while ( 0 )
return false;


Это нецеловое использование цикла, но действительно смотрится элегантнее вложенных проверок.


Ответ на: комментарий от no-such-file

Он не часть Си, но в сишных проектах часто применяется.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от no-such-file

Меток много, функция одна и как правило имеет специфичные аргументы, не свойственные другим функциям.

peregrine ★★★★★
()
Ответ на: комментарий от no-such-file

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

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от anonymous

А чего мне тебе рассказывать? Я могу тебе только предложить запустить интерпретатор питона и почитать

import this
Хоть python далеко не лучший язык со многих точек зрения, но философия у него хорошая.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

Лучше о том как ты собираешься обрабатывать какие-то данные без минимум 3 уровней вложенности. Цикл в отдельном методе всё ещё вложенный цикл, добавь немного рекурсии и вот у тебя уже появились все шансы упасть несмотря на то что код исключительно приятный (и мы избежали целых 2 уровня вложенности, ура!).

anonymous
()
Ответ на: комментарий от anonymous

Лучше о том как ты собираешься обрабатывать какие-то данные без минимум 3 уровней вложенности.

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

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от peregrine

Когда у тебя более двух уровней вложенности циклов

Допустим у меня 2 уровня вложенности. Всё равно 1 goto лучше чем 2 break.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Для освобождения конкретных ресурсов вполне себе.

peregrine ★★★★★
()
Ответ на: комментарий от Deleted

а если не нужно, а если будет второе... а если еще и третье?!

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

anonymous2 ★★★★★
()
Ответ на: комментарий от anonymous

Case должен быть constexpr

он и есть. там арифметика не для компилятора, а для читателя форумчанина.

DonkeyHot ★★★★★
()
Ответ на: комментарий от peregrine

Ну вот яркий пример, когда без goto совсем херово:

$target = &$amiData;
$lastKey = array_pop($update[1]);
foreach ($update[1] as $key) {
    if (!isset($target[$key])) goto noUnset;
    $target = &$target[$key];
}
unset($target[$lastKey]);

noUnset:
AlexAT
()
Ответ на: комментарий от AlexAT

Только не предлагайте рекурсию или условия городить, это в глобальном плане inner loop.

AlexAT
()
Ответ на: комментарий от anonymous

И я о том. Целых три лишних операции вместо одного гото. Мазохизм.

$target = &$amiData; 
$lastKey = array_pop($update[1]); 
$unset = true; 
foreach ($update[1] as $key) { 
    if (!isset($target[$key])) { 
        $unset = false; 
        break; 
    } 
    $target = &$target[$key]; 
} 
if ($unset) unset($target[$lastKey]);

Это называется оверинжиниринг в миниатюре.

- Код превратился в портянку с кучей скобок

- Читабельность ухудшилась

- Ещё лишнюю переменную и три лишних операции получили.

Не то, чтобы это сильно на производительности сказалось, но зачем, если есть удобный и правильный в этом месте гото :)

AlexAT
()
Ответ на: комментарий от AlexAT

а если понадобиться проверять два условия? предлагаешь 2 гото? а если 10? ехал гото через гото... пиши как хочешь, это твое дело, но код получается нерасширяемым.

anonymous
()
Ответ на: комментарий от anonymous

Не, ну можно и из буханки хлеба троллейбус сделать. Но зачем? Я о том как раз и говорю, что каждый инструмент хорош для своей задачи: надо делать гото там где надо, и не делать, где не надо.

Да, если два-десять условий вываливаются в одну точку выхода - почему нет?

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

AlexAT
()
Ответ на: комментарий от AlexAT

Пример по второму

# outer
for (...) {
  # inner 1
  for (...) {
    if (...) goto nextOuter;
    ещё строчек 5
  }

  # inner 2
  for (...) {
      for (...) {
        if (...) goto nextOuter;
        тут строчки 3
      }
  }

  # inner 3
  for (...) {
    ещё строчки 4
  }

  # inner 4
  for (...) {
    строчки 4
  }

nextOuter:
}

Такие случаи бывают. Редко, но бывают. Делить их на функции очень накладно за счёт необходимости вызова и передачи аргументов, код проще чем вызовы.

AlexAT
()
Ответ на: комментарий от AlexAT

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

AlexAT
()
Ответ на: комментарий от AlexAT

if (!isset($target[$key])) goto noUnset;

Это условие. А вообще когда такой алгоритм возник то что-то глобально неправильное с логикой и это костыль. В норме у тебя даже желания творить подобное возникнуть не должно.
PS
Это что, PHP?
PPS
Я не PHP программист, так что могу сильно накосячить с пониманием синтаксиса, однако меня немножко смущает смысл твоего кода, кажись у тебя там баг или фича странная (но в большинстве случаев, как мне кажется именно потенциальный баг, который выскочит при первом же изменении поведения кода, даже без дополнительных условий) от готу виден: ты бегаешь форичем по некоторому массиву с обновленными ключами, если в целевом массиве нет ключа убегаешь куда-то дальше и потом тебе, скорее всего, надо помнить что неплохо бы назад вернуться (у тебя же не всегда один единственный ключ проверяется?). Опять будешь метку с goto втыкать в кодец? Вот и лапша подъехала.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

С синтаксисом там всё просто: есть массив ключей, есть ассоциативный массив рандомного уровня вложенности. Нам надо перейти по этому массиву ключей на энный уровень вложенности в ассоциативном массиве и удалить в нём последний ключ.

А сама задача ещё проще: апдейты из очереди идут почти сплошным потоком штук по 50-500 в секунду либо в качестве набора ключей и к ним значения произвольного типа для 'set', либо в качестве просто набора ключей для 'unset' (и этот кусок приведён). Надо быстро разворачивать данные апдейты в этот самый ассоциативный массив для создания полной карты состояния.

AlexAT
()
Ответ на: комментарий от peregrine

Поэтому откровенное фантазёрство про «неплохо бы назад вернуться» можно оставить за скобками. Это inner loop процесса обработки апдейтов. Выше - outer loop прохода по текущему массиву апдейтов. А выше - вызов собственно этой функции обработки.

AlexAT
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.