Function works inconsistently

Viewed 90

I am new to PHP. I have a function that works (the value printed to the screen from within the function is exactly what I expect), but only sometimes returns the answer (other times it returns NULL). I believe I have isolated the error to something involving my use of the static feature of PHP, but I am not sure how exactly I'm transgressing/how to fix it. I tried to work around it by creating a new non static variable to store the result, and that improved my code from always returning NULL to only sometimes returning NULL. The erring function is part of a larger suite of programs I wrote, so I'll include it and the testing function I use to check that it works.


probGen.php

<?
    require_once("randX.php");
    require_once("../displayArray.php");
    error_reporting(E_ERROR | E_WARNING | E_PARSE);

    function probGen(array $arr, float $control = 0.01) 
/*
*   Generates a valid, random probability distribution for a given array of elements, that can be used in conjunction with "probSelect()".
*   Input: 
        $arr: An array of elements.
        $control: A value that decides how much mass is allowed to be unilaterally dumped onto one element. A high value would permit distributions where most of the mass is concentrated on one element. 
        If an invalid value is provided, the default is used.
*   Output: An associative array where the keys are the elements in the original array, and the values are their probabilities. 
*/
    {
        $control = ($control <= 1 && $control >= 0)?($control):(0.01);  #Use the default value if an invalid number is supplied.
        static $result = [];    #Initialises $result with an empty array on first function call.
        static $max = 1;    #Initialises $max with 1 on first function call.
        foreach ($arr as $value) 
        {
            $x = randX(0, $max);    #Random probability value.
            $result[$value] = ($result[$value] + $x)??0;    #Initialise the array with 0 on first call, and on subsequent calls increment by $x to assign probability mass.
            $max -= $x;     #Ensures that the probability never sums to more than one.
        }
        print("<br>sum = ".array_sum($result)."<br><br>");
        displayArray($result);
/*
*   After the execution of the above code, there would be some leftover probability mass. 
*   The code below adds it to a random element.
*/
        $var = array_values($arr);
        if($max <= $control)    #To limit concentration of most of the probability mass in one variable.
        {
            $result[$var[rand(0,(count($var)-1))]] += $max; #Selects a random key and adds $max to it.
            displayArray($result);
            print("<br>sum = ".array_sum($result)."<br><br>");  
            $sol = $result;
            return $sol;
        }
        else
            probGen($arr, $control);    
    }
?>

test.php

<?

    /*
    *   This file contains some functions that can be used for assigning probabilities to an array of elements or selecting an element from said array with a given probability.
    */
    
    require_once("../displayArray.php");
    require_once("confirm.php");
    require_once("randX.php");
    require_once("probGen.php");
    require_once("probSelect.php");
    
    $test = ["California" => 0.37, "Florida" => 0.13, "New York" => 0.28, "Washington" => 0.22];
    $testX = array_keys($test);
    
    var_dump(probGen($testX));
    
    /*for ($i=0; $i < 100 ; $i++) 
    { 
        print(var_dump(confirm(probGen($testX))));
    }*/
    
?>

Screenshot of probGen() working as intended:
enter image description here

Screenshot of probGen() failing:
enter image description here

From testing I've been able to determine that probGen() fails if the recursion occurs more than once.

1 Answers

As @aynber comment (all credit to him I just wrote that so this post will have an answer).

When calling the recursive call you should add return (at the last line) in order to bubble the return value of probGen function as return probGen();

Generally speaking, having PHP return NULL sometimes may use as hint to case when non value is being returned.

Can see also this question with same issue.

Related