Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

$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 будет только так много:

Как правило, funcname принимает два параметра. Параметр массива значение является первым, а второй/индекс вторым.

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

Ответ 2

use statement фиксирует переменную во время создания функции закрытия.

Регулярные аргументы функции захватывают значение, когда функция называется.

Обратите внимание, что я различался между 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 для переменной , а не только копию значения , что переменная в какой-то момент. Чтобы прояснить мою идею: подумайте о переменной как о небольшом поле, которое может содержать одно значение в любой момент времени, и это значение может быть изменено. И вы можете сделать другую переменную точкой для этого поля, чтобы вы могли обновить значение в поле или прочитать текущее значение в нем.

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

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

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 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 make another bank to prove that it has it 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 test bank1 one more time to be sure that bank2 didn't mess with it.
echo $bank1['getBalance'](); // 5 - still 5, as expected.

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