Эмулировать функциональность goto в PHP 5.2 - может быть, лучший подход? - PullRequest
4 голосов
/ 09 июля 2011

Я написал скрипт, используя мою локальную установку PHP 5.3, используя оператор goto. Загружая его на мой веб-сервер, я обнаружил, что на моем хостере все еще установлен PHP 5.2 и, следовательно, он не поддерживает goto. Поэтому мой вопрос заключается в том, как эмулировать функциональность goto в следующем контексте:

foo();

iterator_start:

foreach ($array as $array_item) {
    switch ($array_item) {
        case A:
            foo();
            break;
        case B:
            // Substitute
            array_splice($array, offset($array_item), 1, array(A, A, B, C));
            // Restart iterator
            goto iterator_start;
            break;
    }
}

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

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

Любые идеи приветствуются.


Вежливый запрос: Пожалуйста, избавьте меня от лекций о полезности или опасностях goto здесь. Я прочитал PHP и оператор goto, который будет добавлен в PHP 5.3 , и знаю о спагетти-коде и всех тех модных "считающихся вредными" письмах 1980-х годов. Обсуждение предполагаемого зла goto не имеет никакого отношения к моему вопросу, и трактовка любой программной конструкции как «плохого стиля» как таковая - это просто догма, которой нет места в моей идеологии программирования.

Ответы [ 5 ]

2 голосов
/ 09 июля 2011

Вы можете использовать each() в цикле while.Он использует внутренний курсор массива для извлечения элемента current в массиве и перемещения курсора к элементу next .При разрезании массива сбросьте курсор, чтобы перезапустить его с начала массива при следующей итерации цикла.Вызов reset(), вероятно, даже не требуется, возможно, это побочный эффект array_splice(), поскольку он меняет массив.

foo();
while (list($key, $array_item) = each($array)) {
  switch ($array_item) {
    case A:
      foo();
      break;
    case B:
      // Substitute
      array_splice($array, offset($array_item), 1, array(A, A, B, C));
      // Reset array cursor, this is probably not necessary 
      reset($array);
      break;
  }
}
1 голос
/ 09 июля 2011

Ну, говорят, что любой goto может быть заменен управляющими структурами, такими как for и while или функциями.

В вашем случае я бы использовал для этого функцию:

function goto_substitute($array){

foreach ($array as $array_item) {
    switch ($array_item) {
        case A:
            foo();
            return $array;
        case B:
            // Substitute
            array_splice($array, offset($array_item), 1, array(A, A, B, C));
            // Restart iterator
            return goto_substitute($array) ;                
    }
}
}

Редактировать (для адресации комментария)

Функции делают код намного более читабельным. Лучшие практики программирования гласят, что функция должна выполнять одну вещь и быть не больше экрана размером (около 80-90 строк) - у вас есть несколько блоков замещения - кажется логичным иметь несколько функций если вы назовете их интуитивно, то кто-нибудь поймет, что там происходит

1 голос
/ 09 июля 2011

рекурсии?Вместо goto iterator_start вы оборачиваете этот цикл в функцию и вызываете его рекурсивно.

0 голосов
/ 09 августа 2013

вы пытались использовать include?Я имею в виду, что вы пишете свой код foreach в файле с именем

foreach.php, например, вместо того, чтобы использовать goto, вы просто используете include ('foreach.php') следующим образом:

foreach ($array as $array_item) {
switch ($array_item) {
    case A:
        foo();
        break;
    case B:
        // Substitute
        array_splice($array, offset($array_item), 1, array(A, A, B, C));
        // Restart iterator
        include('foreach.php'); 

        break;
}

}

0 голосов
/ 09 июля 2011

гото - злой артефакт древних дней. Почему это введено в PHP 5.3, никто не знает. Не используйте это. Когда-либо.

Здесь является отличным объяснением Дейкстры, которое даже предполагает, что некоторые люди с 1959 года не одобряют его. По мере появления большего количества операторов потока управления необходимость в goto еще меньше. Он может иметь конкретное применение при оптимизации какого-либо низкоуровневого, критичного ко времени кода, но нет абсолютно никакой причины использовать его в PHP, и мне еще предстоит увидеть первый пример, где goto будет лучше, чем любое другое решение.

В вашем случае рекурсия может быть лучшим решением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...