Как очистить статическую переменную в PHP после завершения рекурсии?

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

Например, у нас есть функция:

<?php
function someFunction() {
    static $variable = null;
    do stuff; change value of $variable; do stuff;
    someFunction(); # The value of $variable persists through the recursion.
    return ($variable);
}
?>

Мы можем вызвать функцию в первый раз так: someFunction();, и она будет работать нормально. Затем мы вызываем его снова: someFunction();, но на этот раз он начинается с предыдущего значения для $variable. Как мы можем сбросить его после рекурсии в первый раз, когда мы вызвали функцию, чтобы во второй раз это было похоже на запуск заново?


person trusktr    schedule 28.04.2011    source источник
comment
Я не уверен, что понимаю ваш вопрос, но если вы не хотите, чтобы значение переменных сохранялось при рекурсии, просто удалите статику.   -  person austinbv    schedule 28.04.2011
comment
Я хочу, чтобы она сохранялась через рекурсию ... Я не хочу, чтобы она сохранялась, когда я вызываю функцию вручную, вводя ее в исходный код.   -  person trusktr    schedule 28.04.2011
comment
Вот почему мы не используем статические переменные для рекурсии.   -  person Ignacio Vazquez-Abrams    schedule 28.04.2011
comment
Спасибо всем, кто ответил! Все это хорошие, но разные способы делать одно и то же. ;)   -  person trusktr    schedule 28.04.2011


Ответы (5)


Ответ Prodigitalsons - лучшее решение, но поскольку вы запросили решение с использованием статических переменных, я не вижу подходящего ответа, вот мое решение.

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

function someFunction() {
    static $variable = 0;
    $variable++;
    echo $variable;
    if ($variable < 5) someFunction();

    $returnValue = $variable;
    $variable = null;
    return $returnValue;
}
someFunction();
echo "\n";
someFunction();
echo "\n";

Или объедините это с предыдущим ответом с инициализатором:

function someFunction($initValue = 0) {
    static $variable = 0;
    if($initValue !== 0) {
        $variable = $initValue;    
    }
    $variable++;
    echo $variable;
    if ($variable < 5) someFunction();

    $returnValue = $variable;
    $variable = null;
    return $returnValue;
}

someFunction(2);
echo "\n";
someFunction(3);
echo "\n";
someFunction();
echo "\n";
someFunction(-2);

Выведет:

345
45
12345
-1012345
person Bas    schedule 28.11.2014
comment
Помните, что оба этих примера работают случайно, потому что инициализация происходит только один раз за выполнение скрипта, но - к счастью - null приводится к 0 с помощью $variable++. - person aercolino; 05.12.2014
comment
Вы правы, именно это и происходит. В таком случае это не должно быть общепринятым ответом. - person Bas; 08.12.2014

Самый простой способ - передать переменную в качестве аргумента. Я бы не стал здесь связываться со статикой.

function someFunction($value = null) {
    do stuff; change value of $value; do stuff;
    someFunction($value); # The value of $variable persists through the recursion.
    return $value;
}

Как правило, вы должны передавать аргументы функции (если они не работают со свойствами класса в одном и том же классе) ... они не должны быть глобальными, и в случае рекурсии, вероятно, не рекомендуется делать их статическими. .. Относитесь к функции как к черному ящику ... значения входят ... они работают с ними / с ними, и на выходе получается результат. Они не должны знать, что происходит где-то еще. Есть некоторые исключения, но IMO их очень мало.

person prodigitalson    schedule 28.04.2011
comment
Я согласен с тем, что у статических переменных очень мало вариантов использования. Однако сегодня я обнаружил приятный момент: отслеживать номер текущей замены в обратном вызове, переданном preg_replace_callback. Помните, что вам, вероятно, потребуется повторно запустить статический счетчик внутри обратного вызова, например, перед выходом из последней замены. - person aercolino; 05.12.2014

Хорошо, я вижу, что Блудница запутала меня в ответе. Вот демонстрация:

http://codepad.org/4R0bZf1B

<?php
function someFunction($varset = NULL) {
    static $variable = NULL;
    if ($varset !== NULL) $variable = $varset;
    $variable++;
    echo $variable;
    if ($variable < 5) someFunction();
    return $variable;
}

someFunction(4);
echo "\n";
someFunction(2);
echo "\n";
someFunction(3);

?>

Выходы:

5
345
45
person Jared Farrish    schedule 28.04.2011
comment
Ха-ха. Если вы живете где-то рядом с орехом пекан, вы знаете, что белка всегда первой добирается до ореха. - person Jared Farrish; 28.04.2011
comment
<homer-simpson> ммммм засахаренные орехи пекан </homer-simpson> - person prodigitalson; 28.04.2011
comment
Но если вы вызовете функцию без аргумента, переменная никогда не сбросится. Таким образом, последующие вызовы someFunction () будут печатать 6 7 8 и т. Д. - person Bas; 28.11.2014
comment
См. Мой комментарий stackoverflow.com/questions/5812953/. - person aercolino; 05.12.2014

Вы можете использовать счетчик $depth:

function someFunction() {
    static $variable = null, $depth= 0;
    $depth++;

    do stuff; change value of $variable; do stuff;
    someFunction(); # The value of $variable persists through the recursion.

    $depth--;
    $temp = $variable;
    if($depth== 0){
        $variable = null;
    }
    return ($temp);
}
person Think Big    schedule 10.09.2016

Я нашел решение:

<?php
function someFunction($clear_static = false) {
    static $variable = null;
    if ($clear_static) {
        $variable = null;
    }
    do stuff; change value of $variable; do stuff;
    someFunction(); # The value of $variable persists through the recursion.
    return ($variable);
}

someFunction(); # first manual call.
someFunction(); # second manual call, $variable has value from previous use.
someFunction(true); # third manual call, value of $variable starts like new.
?>
person trusktr    schedule 28.04.2011
comment
обратите внимание, как вы можете заменить ключевое слово static ключевым словом global, и оно будет работать так же = ( - person tereško; 28.04.2011
comment
хе-хе, да. Это похоже на один из ответов! ха-ха! Так что же происходит, когда $varset имеет значение NULL и вы ставите ++$variable в своем ответе? - person trusktr; 03.09.2011