Действительно ли возможно моделировать закрытия в PHP 5.2.x не использующий globals? Я мог думать о пути, который передаст желаемые переменные как дополнительные параметры к закрытию, но это просто не чувствует себя подобно лучшей практике.
Какие-либо идеи?
Интересный вопрос. Я бы сказал вообще невозможно, но давайте посмотрим
Цитирование IBM - Что нового в PHP5.3, часть 2
Закрытие - это функция, которая вычисляется в своем собственном окружении, имеющая одну или несколько связанных переменных, к которым можно получить доступ при вызове функции.
и далее (выделено мной)
Переменные, которые должны быть импортированы из внешнего окружения, указаны в пункте use определения закрывающей функции. По умолчанию они передаются значением , что означает, что если бы мы обновили значение, передаваемое внутри определения закрывающей функции, оно не обновляло бы внешнее значение.
Использование global
будет передаваться по ссылке, и хотя можно связать переменные по ссылке с помощью функции закрытия, используя &
в пункте use
, это уже является отклонением от поведения по умолчанию 5.3.
$var = 'yes';
$fn = create_function('', 'global $var; $var = "no";');
$fn();
echo $var; // outputs no
Можно скопировать глобальную переменную, чтобы использовать ее по значению, хотя, например,
$var = 'yes';
$fn = create_function('', 'global $var; $tmp = $var; $tmp = "no";');
$fn();
echo $var; // outputs yes
Кроме того, значение глобальной переменной (при использовании create_function
) не будет вычисляться (привязываться) при создании функции, но при выполнении функции
$var = 'yes';
$fn = create_function('', 'global $var; $tmp = $var; return $tmp;');
$var = 'maybe';
echo $fn(); // outputs maybe
$var = 'yes';
$fn = function() use ($var) { return $var; };
$var = 'maybe';
echo $fn(); // outputs yes
Также важным является
Когда определено внутри объекта, то удобно то, что закрытие имеет полный доступ к объекту через $this переменную, без необходимости явного импорта. *Как мне кажется, в финале PHP5.3
Это невозможно с помощью ключевого слова global
, а также нельзя просто использовать $this
. При определении тела функции с помощью create_function
невозможно ссылаться на свойство из класса. В результате
class A {
protected $prop = 'it works';
public function test()
{
$fn = create_function('', 'echo $this->prop;');
return $fn;
}
}
$a = new A;
$fn = $a->test();
$fn();
приведет к
Fatal error: Using $this when not in object context
Суммируя это
, можно создать функцию, импортирующую переменную из глобальной области видимости, но нельзя создать ее, используя переменные из другой области видимости. А поскольку технически при использовании create_function
вы не привязываете, а импортируете, когда создаваемая функция выполняется, то хотелось бы возразить , что это ограничение делает закрытие лямбдой.
EDIT: Хотя решение, предложенное Онно Марсманом ниже, довольно приличное. Оно не полностью имитирует Closures, но реализация довольно близка.
Ты имеешь в виду Карри, как http://en.wikipedia.org/wiki/Currying
Затем http://zaemis.blogspot.com/2009/06/currying-in-php.html
Если нет, то неважно. :-)
Мое решение: http://techblog.triptic.nl/simulating-closures-in-php-versions-prior-to-php-5-3/
Однако он передает переменные внутри объекта в закрытие в качестве первого аргумента.