В вашем примере возвращаемое значение вызова func1
является функцией (точнее, Closure
). Ошибка, которую вы получаете, связана с тем, что php не может преобразовать этот объект в строку. Если вы хотите напечатать значение, возвращаемое закрытием, вам нужно вызвать его.
function func1() {
return function() {
return 1;
};
}
$f = func1(); // Create the closure
echo $f(); // Calls the closure
Этот пример просто функция, возвращающая функцию и не демонстрирует, что отличает замыкание отдельно от любой другой функции первого класса, а в том, что крышка может содержать состояние уникальной для его создания. Другими словами, вы можете генерировать функции из того же кода, который отличается данными, к которым они могут получить доступ.
Рассмотрим этот тривиальный пример:
function multiplier($m) {
return function ($v) use ($m) {
return $v * $m;
};
}
$mult_5 = multiplier(5);
echo $mult_5(5); // prints 25
$mult_10 = multiplier(10);
echo $mult_10(5); // prints 50
Опять же, это очень тривиальный пример, но демонстрирует несколько важных вещей. Во-первых, мы определили только одну функцию, но, вызвав эту функцию, смогли сгенерировать две аналогичные, но разные функции, просто изменив параметры, когда мы их вызвали. Также учтите, что каждая функция имеет свое «состояние». В случае функции, которую я назвал $mult_5
, она знает, что ее собственное внутреннее значение $m
составляет 5
, и это отличается от значения $m
функции $mult_10
. Значение для каждого из них было передано функции multiplier
, и эта функция завершилась, но значение сохраняется в возвращаемой функции/закрытии.
Стоит также отметить, что каждое возвращаемое значение вызова multiplier
является первой функцией класса, а это означает, что вы можете написать обобщенные функции (например, multiplier
), а затем использовать их для создания более конкретных функций «на лету» , функции, которые более конкретно подходят для текущей среды/состояния вашей программы.
Если вы знакомы с объектно-ориентированным программированием, приведенный выше пример может быть легко переписан с использованием ООП:
class Multiplier {
protected $m;
public function __construct($m) {
$this->m = $m;
}
public function multiply($v) {
return $v * $this->m;
}
}
$mult_5 = new Multiplier(5);
echo $mult_5->multiply(5); // prints 25
$mult_10 = new Multiplier(10);
echo $mult_10->multiply(5); // prints 50
... и это очень субъективно, но я предпочитаю более consice синтаксис закрытие.
В качестве альтернативы, вы могли бы просто использовать более общую функцию, чтобы начать с:
function multiplier($a, $b) {
return $a * $b;
}
echo multiplier(5, 5);
echo multiplier(5, 10);
Но выгода от использования закрытия вместо является то, что вы можете скрыть данные (например, мультипликатора, в данном примере).
* Этот * не очень полезен, но другие могут быть: 'function make_adder ($ x) {return function ($ y) use ($ x) {return $ x + $ y; }} 'позволяет вам делать что-то вроде' $ adder = make_adder (3); echo $ сумматор (2); // печатает 5'. –
Вышеприведенный пример может использоваться для [currying] (http://stackoverflow.com/questions/36314/what-is-currying) функций, что исключительно полезно. – Orbling
Порекомендуйте вам провести некоторое время с более функциональным языком, что даст вам лучшее представление о том, как использовать функциональное программирование. Затем, когда вы вернетесь к PHP, вы найдете новые закрытия, анонимные функции и теперь более полезные функции обратного вызова, гораздо более полезными. – Orbling