I’m having a hard time figuring out how to implement code similar to the following Python code:
class _Mapper(object): # Holds the name of the function to call when we want to predict a value. # There may be dozens of these _Mapper objects stored in an array which are # created by calling _create_couplet() in a nested loop def __init__(self, estimator): self.estimator = estimator def _create_couplet(pairings, A, B): # Gets the data for the pairing from the pairings class and returns a Mapper # object containing the function (either function 1 or function2 - defined in # pairing class) that we'll use to to predict the value if A < B: return (_Mapper(pairings.function1)) else: return (_Mapper(pairings.function2)) # Use the function (either function1 or function2) stored in _Mapper.estimator # (created by _create_couplet) to estimate the new value based on the old value newValue = _Mapper.estimator(oldValue)
Essentially it creates an array of _Mapper objects and each object contains a reference to a function (either function1 or function2) which is later used to calculate a value. The crucial steps seems to be:
newValue = _Mapper.estimator(oldValue)
which takes the function held in _Mapper.estimator and then passes oldValue to as if it was newValue = function1(oldValue) or newValue = function2(oldValue)
I’m trying to implement something similar in PHP but I seem to get some kind of infinite loop when running this in the CLI. It appears that the function name is not stored in the
class Pairings { // Define the two functions (these are just placeholders) public function function1($value = null) { return $value * 2; } public function function2($value = null) { return $value * 4; } } class _Mapper { function __construct($estimator) { // This should store the function that we are going to // use based on the value of A & B in _create_couplet() $this->estimator = $estimator; } function estimator($value) { // This should pass the value specified to either function1() // or function function2() and should return the result. It // doesn't ! return $this->estimator($value); } } function _create_couplet($pairing, $A, $B) { // Based on the value of A or B store the appropriate function if ($A < $B) { return (new _Mapper($pairing->function1())); } else { return (new _Mapper($pairing->function2())); } } // Set up some values $oldValue = 10; $A = 10; $B = 5; // Define the pairing $pairing = new Pairings; // Create the _Mapper object $couplet = _create_couplet($pairing, $A, $B); // Pass oldValue into the appropriate function and get the result back $newValue = $couplet->estimator($oldValue); echo ("New value: $newValue");
I’m sure that I’ve made a simple mistake but I can’t see what I’ve missed. How can I store a function name in an object and then pass a parameter into it so that the stored function uses that parameter and returns a value ?
Advertisement
Answer
There are two issues :
in your _create_couplet
method, the argument you’re giving to new _Mapper()
is not the function to execute, but the function result. You’re executing $pairing->function1()
and it performs null * 2
because you’re allowing null
values, otherwise it should have failed because you’re calling function1
without argument.
As Lars suggested you should use a callable argument :
//before new _Mapper($pairing->function1()); //after new _Mapper([$pairing, 'function1']);
THe second issue which provokes the infinite loop is that you try to call this callable in the estimator
method, which is calling $this->estimator()
. You may think that $this->estimator()
refers to your callable contained in $this->estimator
, but as you have a method with the same name, PHP will think you’re calling the method and not the property.
THe simplest way to fix it is to name either the method or the property differently.