JackJones's avatar

Help with recursion

Is there a way to not have to pass an intended returned variable back into a function?

function do_this($a, $to_return = [])
{
    // do some stuff

    if(condition) {
               return do_this($a, $to_return);
    }

    return $to_return;
}

I'm trying to get away from having to pass $to_return into the function at all

It isn't the end of the world but it looks a bit odd putting it it

0 likes
12 replies
ahmeddabak's avatar

You can use a variable by reference then you do not have to return it

cmdobueno's avatar
function do_this($a, $to_return = [])
{
    // do some stuff

    if(condition) {
               return do_this(&$a, &$to_return);
    }

    return $to_return;
}

add an & before a variable in the function call... I added it to both variables as I have no clue which would be modified by the call...

andreich1980's avatar

Can you describe your logic? Why do you need the $to_return array at all?

1 like
cmdobueno's avatar

If you provide us a bit more meat and potatoes to what you are trying to accomplish, we may be able to help more.

There are times where recursion is actually not required and there are better ways to accomplish things.

JackJones's avatar
    /**
     * Get a list of titles from a Wikipedia Category
     *
     * @param  string $title     [description]
     * @param  array  $to_return [description]
     * @return [type]            [description]
     */
    public function getCategoryList(string $title, string $continue = '', array $to_return = []): array
    {
        $title    = str_replace('_', ' ', $title);
        $response = $this->getResponseFromWikipedia('category', str_start($title, 'Category:') . $continue);

        foreach ($response['query']['categorymembers'] as $place) {
            if ($place['title'] != $title and !preg_match('/^User/i', $place['title'])) {
                $to_return[] = $place['title'];
            }
        }

        if (isset($response['continue'])) {
        // HERE
            return $this->getCategoryList($title, '&cmcontinue=' . $response['continue']['cmcontinue'], $to_return);
        }

        return $to_return ?? [];
    }

Nothing gets passed to the $to_return variable initially, it is only there for the recursion, to build up the array

I was just wondering if there was a way to not have to pass it

cmdobueno's avatar

@jackjones

Can you give me an example of each variable?

$title, $continue... of this function call. I think I know what you want to do here, but I need to verify with these variables... and then I should be able to help you.

Nash's avatar

Perhaps you could use a class variable instead?

private $some_variable = [];

...and in your method:

$this->some_variable[] = "something"; // or something similar depending on your needs
1 like
JackJones's avatar

@NASH - That is the other option but I was avoiding it because I wish being really strict about it i.e. the other methods don't need access to it (debatably unnecessarily and because my way works equally as well) and I wondered if there was another way

JackJones's avatar

@CMDOBUENO - they are both strings ref:

getCategoryList(string $title, string $continue = ''
Talinon's avatar

You could always extract it all to its own dedicated class with the sole responsibility of the recursion. Then you can set your class property within the dedicated class with confidence that nothing else will access it.

lostdreamer_nl's avatar

Here you go...... you just needeed to merge the result of the recursed function back into your $to_return variable ;)


    public function getCategoryList(string $title, string $continue = ''): array
    {
        $to_return = [];
        $title    = str_replace('_', ' ', $title);
        $response = $this->getResponseFromWikipedia('category', str_start($title, 'Category:') . $continue);

        foreach ($response['query']['categorymembers'] as $place) {
            if ($place['title'] != $title and !preg_match('/^User/i', $place['title'])) {
                $to_return[] = $place['title'];
            }
        }

        if (isset($response['continue'])) {
            // HERE
            $tmp = $this->getCategoryList($title, '&cmcontinue=' . $response['continue']['cmcontinue']);
            $to_return = array_merge($to_return, $tmp);
        }

        return $to_return ;
    }

Please or to participate in this conversation.