Reputation: 4288
I have a method which gets a callable as an argument. The callable is called with some arguments which can be gotten by-value or by-reference, and it may return a value, either by-value or by-reference, or not. In the case of returning a value, it must be returned from the closure by the method as exactly as is. If the value is by-reference, the method must return it by-reference, and vice versa.
The problem is that there is no way to determine whether the value is returned by-reference or not. Yes, it can be detected whether the closure returns any values or not; but when I try to get the reference of a closure's return value which is returned by-value, I will get the following notice:
PHP Notice: Only variables should be assigned by reference in ... on line xxx
Again, the method returns the closure's return value as is (i.e. dynamically). This is what I try to achieve:
class Example
{
protected $data = 15;
// Pay attention to this, returning by-reference
protected function &doOnData(callable $function)
{
return $function($this->data);
}
public function increment(): void
{
// No notices, because the closure is defined to return by-reference
$data = &$this->doOnData(function &(&$data) {
return $data;
});
$data++;
}
public function get()
{
// Notice, why you defined the closure to return by-value?
// Defining the closure to return by-reference fixes the problem
// temporarily (i.e. defining as: function &($data))
return $this->doOnData(function ($data) {
return $data;
});
}
public function printData()
{
echo $this->data;
}
}
$example = new Example();
$example->increment();
$example->printData(); // Prints: 16
$data = $example->get(); // Notice!
echo $data; // Prints: 16
As you see in the example, the notice will only be produced when you pass a returning-by-value closure to Example::doOnData()
, and you cannot get its return value reference. In this case, the above notice will be generated (should it be generated? I don't know!).
A solution might be using the @ (at sign) operator, which is stupidly bad (see: 1 and 2). Saving the reference of the closure to a variable, and then returning the variable doesn't change anything (AFAIK). Also, adding an ampersand (&) before the closure inside Example::get()
, as described in code comments, is not a solution for that, and have some side effects (e.g. every closure must be defined to return by-reference to prevent the notice, too bad, the user doesn't know that). So, please don't suggest these things!
Is there any way to prevent the notice? Am I doing something wrong? Generally speaking, can I determine whether the value is returned by-value or by-reference (i.e. something like is_reference()
)? Is there any other solutions to get it done?
Upvotes: 1
Views: 153