php function looping and finally return processed array

function test($a, $b){
    $arr = [$a, $b];

    if($a == 1){
        echo "first here";
        test(3,4);
    }
    else{
        echo "second here";
        return [$a, $b];
    }
    echo "should have returned earlier";
    return $arr;
}

$arr = test(1,2);
print_r($arr);

I am expecting [0 => 3, 1 => 4] but receiving [0 => 1,1 => 2]

Can anyone explain how is it returning?

Upvotes: 2

Views: 75

Answers (4)

CJ Dennis
CJ Dennis

Reputation: 4336

Here is your code annotated:

function test($a, $b){
    $arr = [$a, $b];

    if($a == 1){
        echo "first here";
        test(3,4);  // Return value from recursive call discarded
    }
    else{
        echo "second here";
        return [$a, $b];    // if $a != 1, will return here
    }
    echo "should have returned earlier";
    return $arr;    // if $a == 1, will always return here
}

If you follow all the possible paths through, you'll see that the function always returns [$a, $b] since the return value from test(3,4) is immediately discarded, and the function continues.

The change that is needed to get the output you are expecting is:

-         test(3,4);
+         return test(3,4);

At this point, you don't need the final two lines, since both branches of the if are returning:

-     echo "should have returned earlier";
-     return $arr;

Now $arr is not used, so it can be removed too:

-     $arr = [$a, $b];
- 

This gives:

function test($a, $b) {
    if ($a == 1) {
        echo "first here";
        return test(3, 4);
    }
    else {
        echo "second here";
        return [$a, $b];
    }
}

However, some people don't like multiple returns / early returns. You can use the following code instead:

function test($a, $b) {
    if ($a == 1) {
        echo "first here";
        $arr = test(3, 4);
    }
    else {
        echo "second here";
        $arr = [$a, $b];
    }
    return $arr;
}

Consider adding extra spaces like I have done for readability. If your function should only work with integers consider === instead of ==. I also recommend using a good unit test framework with code coverage. That way you can see which lines were executed (but not in which order) which would help you to find, understand and fix bugs.

Upvotes: 2

Dawid Zbiński
Dawid Zbiński

Reputation: 5826

You should return a recursive function, when you're dealing with recursion.

function test($a, $b){
    $arr = [$a, $b];

    if ($a === 1) {
        echo "first here";
        return test(3,4);
    }
    // ELSE is not needed as if $a === 1 the program will never get here
    echo "second here";
    return [$a, $b];
}

$arr = test(1,2);
print_r($arr);

Please, consider updating your question by precisely specifying desired output and behavior. You should also consider changing your code, if the one I have created for you is your desired outcome, as it's not dynamic and probably have no use case.

Upvotes: 3

Niklesh Raut
Niklesh Raut

Reputation: 34914

What you need to assign returned value into $arr

$arr = test(3,4);

Live demo

Upvotes: 0

Blue
Blue

Reputation: 22911

At no point are you trying to return 3, 4. You call it via test(3,4) in your code, which in that code will "return" the value but you're not actually doing anything with it, you simply call it. Your code continues to run, and then returns $arr which is [1, 2] which was originally passed in.

You can see this, by seeing the return value of test(3,4):

<?php
function test($a, $b){
    $arr = [$a, $b];

    if($a == 1){
        echo "first here";
        // Put the return of test(3,4) into $ret
        $ret = test(3,4);
        print_r($ret);
    }
    else{
        echo "second here";
        return [$a, $b];
    }
    echo "should have returned earlier";
    return $arr;
}

$arr = test(1,2);
print_r($arr);

Remember, $a and $b are never overwritten. Each variable exists in the function it was run in, and then ceases to exist afterwards. This is what makes re-usability of functions so important.

Upvotes: 1

Related Questions