Вопрос по php – В чем разница между параметрами закрытия и ключевым словом use?

18

Это очень смутило меня, и я не могу найти ответ на этот вопрос. Четкое и простое уточнение было бы неплохо.

Я думаю, что вы выбрали неправильный ответ Trix

Ваш Ответ

2   ответа
25

use statement захватываетvariable в то времяclosure function is created.

Обычные аргументы функции фиксируютvalue когда функцияcalled.

Обратите внимание, что я различалvariable а такжеvalue там.

function makeAnAdder($leftNum) {
    // Notice that *each time* this makeAnAdder function gets called, we 
    // create and then return a brand new closure function.
    $closureFunc = function($rightNum) use ($leftNum) {
        return $leftNum + $rightNum;
    };

    return $closureFunc;
}

$add5to = makeAnAdder(5);
$add7to = makeAnAdder(7);

echo $add5to(10); // 15
echo $add7to(1); // 8

Если бы был способ проверить «исходный код»? из$add5to функция, это будет выглядеть так:

function($rightNum) {
    return 5 + $rightNum;
}

Я думаю, вы могли бы сказать, что$leftNum запомнился функцией закрытия.

Я хочу еще раз подчеркнуть, чтоuse statement позволяет поддерживатьreference кvariableа не просто копияvalue что переменная имела в какой-то момент. Чтобы прояснить мою идею: представьте, что переменная представляет собой небольшой блок, который может содержать одно значение в любой момент времени, и это значение можно изменить. И вы можете сделать еще одну переменную, указывающую на этот блок, чтобы вы могли обновить значение в блоке или прочитать текущее значение в нем.

Обычно локальная переменная, которая создается внутри функции, перестает существовать после ее возврата. Но функция замыкания может поддерживать ссылку на эту переменную и приводить к тому, что локальная переменная будет жить даже после возврата из функции - и это истинная сила функций замыкания. Это позволяет вам подражать определенному поведению класса (переменным экземпляра) с помощью небольшого кусочка кода.

Вот более сложный пример, который может потребовать некоторых глубоких размышлений, чтобы понять тонкие детали поведения.

function makeBankAccount() {
    // Each time this makeBankAccount func is called, a new, totally
    // independent local variable named $balance is created.
    $balance = 0;

    // Also, on each call we create 2 new closure functions, $modifyBalance, and $getBalance
    // which will hold a reference to the $balance variable even after makeBankAccount returns.
    $modifyBalance = function($amount) use (&$balance) {
        $balance += $amount;
    };

    $getBalance = function() use (&$balance) {
        return $balance;
    };

    // return both closure functions.
    return ['modifyBalance' => $modifyBalance, 'getBalance' => $getBalance];
}

// Let's prove that bank1 works by adding 5 to the balance by using the first
// function, then using the other function to get the balance
// from the same internal variable.
$bank1 = makeBankAccount();
$bank1['modifyBalance'](5);
echo $bank1['getBalance'](); // 5 - it works.

// Now let's make another bank to prove that it has it's own independent internal $balance variable.
$bank2 = makeBankAccount();
$bank2['modifyBalance'](10);
echo $bank2['getBalance'](); // 10 - as expected. It would have printed 15 if bank2 shared a variable with bank1.

// Let's test bank1 one more time to be sure that bank2 didn't mess with it.
echo $bank1['getBalance'](); // 5 - still 5, as expected.

Вы могли заметить, что я использовалсправочный оператор & в этом примере. Если вы еще не знакомы с ними, просто знайте, что ссылки, как известно, трудно понять. Хотя, я надеюсь, что этот пост в основном имеет смысл сам по себе.

Error: User Rate Limit Exceeded$rightnumError: User Rate Limit Exceeded Seralize
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
21

которая оценивается в ее собственной среде, которая имеет одну или несколько связанных переменных, к которым можно обращаться при вызове функции. Они происходят из мира функционального программирования, где существует множество концепций. Замыкания похожи на лямбда-функции, но умнее в том смысле, что они способны взаимодействовать с переменными из внешней среды, в которой задано замыкание.

Ключевое слово use () позволяет вам импортировать переменные извне функциональной среды, внутри функции. Переменные, которые должны быть импортированы из внешней среды, указаны в разделе use определения функции closure. По умолчанию они передаются по значению. Итак, допустим, что функция не имеет параметров, но вы хотите использовать переменную, которая у вас уже есть.

$string = "Hello World!";
$closure = function() use ($string) { echo $string; };

Это полезно, когда вам нужно создать функцию, которая должна использоваться как обратный вызов где-то еще, и может иметь только определенные параметры. Ключевое слово use () позволяет вам использовать другие переменные в дополнение к переменным, которые вы передаете в качестве аргументов функции. Например, на примере php.net:http://php.net/manual/en/functions.anonymous.php

public function getTotal($tax)
    {
        $total = 0.00;

        $callback =
            function ($quantity, $product) use ($tax, &$total)
            {
                $pricePerItem = constant(__CLASS__ . "::PRICE_" .
                    strtoupper($product));
                $total += ($pricePerItem * $quantity) * ($tax + 1.0);
            };

        array_walk($this->products, $callback);
        return round($total, 2);
    }

$ callback должен иметь только два параметра, потому что array_walk будет позволять только это:

Typically, funcname takes on two parameters. The array parameter's value being the first, and the key/index second.

Так что мы можем сделать? Мы называемuse() добавить другие переменные, которые не входят в область действия $ callback, но находятся в области действия среды, в которую она вызывается.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededuse()Error: User Rate Limit Exceeded Seralize
Error: User Rate Limit Exceeded$closure = function($string) { echo $string; };? Seralize

Похожие вопросы