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?

andrewsi
  • 10,807
  • 132
  • 35
  • 51
Leonid
  • 55
  • 2
  • 10
  • 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. – andrewsi Jun 01 '16 at 21:12
  • have you seen the recursive function ? – Yehia Awad Jun 01 '16 at 21:12

2 Answers2

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 ...

Rizier123
  • 58,877
  • 16
  • 101
  • 156
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.

VolkerK
  • 95,432
  • 20
  • 163
  • 226
  • 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 Jun 01 '16 at 21:35
  • @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 ;-) – VolkerK Jun 01 '16 at 21:51