читал мануал и наткнулся на простенький листинг, который привожу ниже (добавил переводы строк и вардамп): Код (Text): <?php function test() { static $count = 0; $count++; echo $count."<br>"; if ($count < 10) { test(); } $count--; echo "<br>"; var_dump($count); //решил проверить результат } test(); в ответ на что получаю следующее : на мануале про такое нечего не заметил. ведь декремент/инкремент увеличивает/уменьшает на 1 ед., а не до 0. объясните или киньте почитать чего-то, я удивлен. з.ы. знаю, что вопрос даунский, но не могу понять причину такого рез-та. только догадки
рекурсия выполняется при условии, что $count < 10, а когда эта переменная достигает цифры 10, то вызов рекурсии должен опускаться и происходить декремент на 1 единицу, - в моем понимании ситуации. Добавлено спустя 36 секунд: в данном случаем ведь рекурсия только увеличивает постепенно $count
Тут все очень просто. Пока $count не дойдет до 10, функция будет раз за разом сваливаться в саму себя, увеличивая значение. При этом остальной код в функции выполняться не будет. Он будет ждать, пока ранее вызванная функция не закончит работу. В итоге у тебя порождается очередь из 10 подряд ожидающих декрементов. Не одного, а десяти. Они и откатывают переменную в ноль. Попробуй на листочке нарисовать функцию как прямоугольник, а из середины выходит стрелочка в такой же прямоугольник, из середины которого выходит стрелочка... Все, что ниже точки, из которой выходит стрелочка, ждет, пока отработает то, куда стрелочка показывает. И сначала отработают все фрагменты до стрелочки от первого прямоугольника до последнего. А потом отработают все фрагменты после стрелочки, от последнего прямоугольника до первого. Это называется коллстэк или стэк вызовов. Именно стэк, а не очередь, обрати внимание. Очередь - это FIFO, first input, first output , стэк - это LIFO, last input, first output. Рекурсивные вызовы функции порождают именно вложенность. Они работают не параллельно. При вызове любой функции, в коллстэк подается соответствующая запись. По завершению функции, запись снимается. При этом данные, созданные в элементе, который имеет уровень иерархии выше остаются в оперативной памяти. Об этом очень важно помнить.
т.е. по сути рекурсивные функции работают как стек? на данном примере с листингом я понял, как это работает, но вот в моей предыдущей теме (про факториал) я использовал опять рекурсию. Код (Text): function factorial($number) { if ($number == 0 or $number ==1) return 1; $result = $number*factorial($number-1); return $result; } значит, что $result будет ожидать n-количество... не знаю, как назвать, проходов?... функции. в данном случае это тоже стек, ведь в обратном порядке порядке ему нечего отдавать не нужно. запутался
Функции всегда через стек работают. Из стека берутся аргументы, ту да же помещаются локальные переменные. У вас тут локальная переменная $result и параметр $number. Даже если функция не рекурсивная, эти значения интерпретатор поместит в стек. И только благодаря этой особенности рекурсия вообще возможна и полезна. [offtop] Помню, в ВУЗе препод никак не мог рассказать группе, чтоб все поняли, как работает алгоритм обхода бинарного дерева. А я это уже знал. И он был очень удивлён, когда я встал, и нарисовал на доске стек, как меняется в процессе работы алгоритма вершина стека, и т.п. [/offtop]
Нет, он будет ожидать ровно один. Там прописан ровно один вызов. И он его ждет. Ему плевать, что там внутри. А внутри еще один $result и он ждет еще один вызов. И так вглубь. Потом, когда последняя вложенная функция отработала, она отдает свой результат наверх. Там, он, согласно твоей формуле, умножается на $number и передается наверх, там, он, согласно твоей формуле... В итоге ты собираешь урожай в виде конечного результата.