LINUX.ORG.RU

Замыкания в PHP: обьясните нубу

 ,


0

1

Добрый день! Есть у меня вот такой кусок кода:

$data = [
	...
	'sex' => function(){
		$sex = ['М', 'Ж'];
		return shuffle($sex)[0];
	}
	...
];

echo $data['sex'];
Получаю ошибку:

Catchable fatal error: Object of class Closure could not be converted to string

Не понимаю, что возвращает функция-замыкание?

echo $data['sex']();

anonymous
()

А возможно ли вообще как-либо вызывать эту функцию сразу? Чтобы в массив попал результат её выполнения, а не обьект типа Closure?

shooter93 ★★
() автор топика
Ответ на: комментарий от shooter93
(function(){
		$sex = ['М', 'Ж'];
		return shuffle($sex)[0];
	})()

Без понятия, работает ли это в PHP.

x3al ★★★★★
()

$data['sex'] и есть не строка, это функция. Чтобы функция вернула строку, надо ее вызвать.

amomymous ★★★
()

'sex' => rand(0, 1) ? 'M' : 'F';

ы?

redixin ★★★★
()
Ответ на: комментарий от newKingOfTheBlock

Потому что так реализовали. То, что мы имеем в первом посте — это обычная анонимная функция. Замыканием же она становится только после того, как она заюзает какую-либо переменную из области видимости уровнем выше:

$sex = ['М', 'Ж'];
$data = [
    'sex' => function () use ($sex) {
        return shuffle($sex)[0];
    }
];

echo $data['sex']();
Kilte ★★★★★
()
Ответ на: комментарий от Kilte

function () use ($sex)

Особые уличные замыкания, лол.

anonymous
()

А возможно ли вообще как-либо вызывать эту функцию сразу?

class MyGenderClosure
{
    private $_sex = array('М', 'Ж');
    public function __toString()
    {
        $this->_run();
        return current($this->_sex);
    }
    private function _run()
    {
        shuffle($this->_sex);
    }
}

$data = array('gender' => new MyGenderClosure());

echo $data['gender'] . PHP_EOL; // М
echo $data['gender'] . PHP_EOL; // Ж
echo $data['gender'] . PHP_EOL; // М
echo $data['gender'] . PHP_EOL; // М
echo $data['gender'] . PHP_EOL; // Ж
deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от shooter93

А возможно ли вообще как-либо вызывать эту функцию сразу?
Похоже что мне нужен call_user_func()

Да:

call_user_func(function () use ($sex) {
    return shuffle($sex)[0];
})

Если надо с аргументами, то можно юзать ещё call_user_func_array.

ProtoH
()
Ответ на: комментарий от ProtoH

Если надо с аргументами, то можно юзать ещё call_user_func_array.

Уточню. С аргументами можно по-разному:

call_user_func(function () {}, $arg1, $arg2, ..., $argN);
// тоже самое, но аргументы перадаются как массив:
call_user_func_array(function () {}, [$arg1, $arg2, ..., $argN]);

ProtoH
()
Ответ на: комментарий от ProtoH

В PHP 7 работают и такие вещи:

$args = ['a', 'b', 'c'];
(function () { var_dump(func_get_args()); })(...$args);
array(3) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "c"
}

или:
$args = ['a', 'b', 'c'];
(function (...$args) { var_dump($args); })(...$args);
array(3) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "c"
}

ProtoH
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.