1

There is a function:

<?php 

 function test(){

     static $count = 0; 
     $count++;  
     echo $count;

     if ($count < 10) {
          test();
     }       

     $count--;  
     echo $count;
}

test();  

?>

This code produces: 123456789109876543210

When $count increments to 10 - its understandable, it works until if statement evaluates to false. but why it gradually decreases to 0? In my newbie logic, $count-- in this code should only decrease to 9 one time and a function should stop. There is no loop or cycle which can reduce its value step by step. But we see, that its here and working. Why it happens?

2
  • 3
    Why should the function stop after the first decrement? You've created a recursive function - effectively the first half of the function runs, then a new instance of the function is created if $count < 10 is true. When that is eventually false, the second half of the function runs; each instance of the function then carries on from where it left off, unwinding through all the functions calls. Commented Jun 1, 2016 at 21:12
  • have you seen the recursive function ? Commented Jun 1, 2016 at 21:12

2 Answers 2

2

Perhaps things get a bit clearer when you change the output to emphasis how the conditional recursive call works:

<?php
function test($level=0) {
    static $count = 0;
    $count++;
    echo str_pad('a:', $level+2, ' ', STR_PAD_LEFT), $count, PHP_EOL;

    if ($count < 10) {
        test($level+1);
    }

    $count--;
    echo str_pad('b:', $level+2, ' ', STR_PAD_LEFT), $count, PHP_EOL;
}

test();

prints

a:1
 a:2
  a:3
   a:4
    a:5
     a:6
      a:7
       a:8
        a:9
         a:10
         b:9
        b:8
       b:7
      b:6
     b:5
    b:4
   b:3
  b:2
 b:1
b:0

Your problem seems to be understanding how the function call(s) and subsequent return(s) from the function works. Let's start simple

<?php
function c() {
    echo 'c in', PHP_EOL;
    echo 'c out', PHP_EOL;
}

function b() {
    echo 'b in', PHP_EOL;
    c();
    echo 'b out', PHP_EOL;
}

function a() {
    echo 'a in', PHP_EOL;
    b();
    echo 'a out', PHP_EOL;
}

a();

prints

a in
b in
c in
c out
b out
a out

Easy enought, isn't it? When a function exits/returns the execution continues at the point where the call was made. And that isn't bound to the name of the function, but the function call itself, see e.g. https://en.wikipedia.org/wiki/Call_stack .
So even if a function calls itself like

<?php
function foo($param) {
    echo "foo($param) in", PHP_EOL;
    if ( $param!==1 ) {
        foo(1);
    }
    echo "foo($param) out", PHP_EOL;
}

foo(0);

that doesn't cause a single exit/return to cancel all function calls of the "same" function, but it just bubbles up one "scope"/frame in the call stack. Therefore the output is

foo(0) in
foo(1) in
foo(1) out
foo(0) out

Now compare that to the output of the "improved" script above: I hope that clears things up a bit for you.

Sign up to request clarification or add additional context in comments.

2 Comments

I really love the different examples, especially the second one with "in" and "out" to represent the code before and after calling the function in OP's code.
@Rizier123 It's the only way I know to visualize something like that in a place like SO ;-) On the other hand it's precisely what I want developers not to do: trace execution flow with strinkydinky printf-debuggers ;-)
2

Okay, so I try to visualize what happens here, so you might get a better understanding of what is going on.

This is what happens (abstract):

//Iteration 1
function(){
    //Code before runs

    if stmt (TRUE)   //Iteration 2   
        function(); → function(){
               ←┐         //Code before runs
    //Code after│
}               │         if stmt (TRUE)          //Iteration 10  
                │             function(); → ... → function(){
                │                        ←┐           //Code before runs
                │         //Code after    │
                │     }                   │           if stmt (FALSE)
                └──── ← function returns  │
                        value and goes    │           //Code after runs
                        back to next line │       }
                                          └────── ← function returns value and goes back to next line


  • So in the 10th function call the if statement is FALSE and doesn't call anymore functions.

  • Now the 10th call the function runs to the end and decreases the variable.

  • It returns the return value(NULL) and goes back to the previous function call which executes the rest of the function call, which also decreases the variable and so on ...

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.