복붙노트

PHP에서 클로저는 무엇이며 "사용"식별자를 사용하는 이유는 무엇입니까?

PHP

PHP에서 클로저는 무엇이며 "사용"식별자를 사용하는 이유는 무엇입니까?

일부 PHP 5.3.0 기능을 체크 아웃하고 꽤 재미있어 보이는 사이트의 일부 코드를 실행했습니다 :

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

    $callback =
        /* This line here: */
        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);
}

익명 함수에 대한 예제 중 하나로

아무도 이것에 대해 알고 있습니까? 어떤 문서입니까? 그리고 사악 해 보입니다.

해결법

  1. ==============================

    1.이것이 PHP가 클로저를 표현하는 방법입니다. 이것은 전혀 사악하지 않으며 사실 강력하고 유용합니다.

    이것이 PHP가 클로저를 표현하는 방법입니다. 이것은 전혀 사악하지 않으며 사실 강력하고 유용합니다.

    기본적으로 이것은 익명 함수가 범위 밖의 지역 변수 (이 경우에는 $ tax 및 $ total에 대한 참조)를 "캡처"하여 해당 값을 유지하도록 허용한다는 것을 의미합니다 (또는 $ total의 경우 참조 ~ $ total 자체)를 익명 함수 자체의 상태로 사용합니다.

  2. ==============================

    2.더 간단한 대답.

    더 간단한 대답.

    함수 ($ quantity) 사용 ($ tax, & $ total) {..};

    @Mytskine은 아마도 클로저에 대한 RFC가 가장 깊이있는 설명이라고 지적했습니다. (그를 위해 Upvote.)

  3. ==============================

    3.폐쇄가 아름답습니다! 그들은 익명의 함수로 많은 문제를 해결하고, (적어도 우리가 PHP에 관해서 이야기하는 한) 정말 우아한 코드를 가능하게합니다.

    폐쇄가 아름답습니다! 그들은 익명의 함수로 많은 문제를 해결하고, (적어도 우리가 PHP에 관해서 이야기하는 한) 정말 우아한 코드를 가능하게합니다.

    자바 스크립트 프로그래머는 항상 닫힌 변수를 명시 적으로 정의하지 않았기 때문에 클로저를 항상 사용합니다. 즉, 바인딩 변수가 명시 적으로 정의되지 않았기 때문입니다. 즉, "사용"은 PHP에서 사용됩니다.

    위의 것보다 더 실제적인 예가 있습니다. 다차원 배열을 하위 값으로 정렬해야하지만 키가 변경된다고 가정 해 보겠습니다.

    <?php
        function generateComparisonFunctionForKey($key) {
            return function ($left, $right) use ($key) {
                if ($left[$key] == $right[$key])
                    return 0;
                else
                    return ($left[$key] < $right[$key]) ? -1 : 1;
            };
        }
    
        $myArray = array(
            array('name' => 'Alex', 'age' => 70),
            array('name' => 'Enrico', 'age' => 25)
        );
    
        $sortByName = generateComparisonFunctionForKey('name');
        $sortByAge  = generateComparisonFunctionForKey('age');
    
        usort($myArray, $sortByName);
    
        usort($myArray, $sortByAge);
    ?>
    

    경고 : 테스트되지 않은 코드 (필자는 php5.3 atm이 설치되지 않았습니다), 그런 식으로 보일 것입니다.

    한 가지 단점이 있습니다. 많은 PHP 개발자가 클로저를 사용하여 대면하면 약간의 도움이 될 수 있습니다.

    클로저의 멋진 ty를 더 이해하기 위해, 나는 자바 스크립트에서 이번에 또 다른 예를 들어 줄 것이다. 문제 중 하나는 범위 지정과 브라우저 고유의 비동기입니다. 특히, window.setTimeout (); (또는 -interval). 따라서 setTimeout에 함수를 전달하지만 매개 변수를 제공하면 코드가 실행되므로 실제로 매개 변수를 제공 할 수 없습니다!

    function getFunctionTextInASecond(value) {
        return function () {
            document.getElementsByName('body')[0].innerHTML = value; // "value" is the bound variable!
        }
    }
    
    var textToDisplay = prompt('text to show in a second', 'foo bar');
    
    // this returns a function that sets the bodys innerHTML to the prompted value
    var myFunction = getFunctionTextInASecond(textToDisplay);
    
    window.setTimeout(myFunction, 1000);
    

    myFunction은 일종의 미리 정의 된 매개 변수가있는 함수를 반환합니다!

    솔직히 말해서, 나는 5.3과 익명의 함수 / 클로저보다 더 많은 것을 좋아한다. 네임 스페이스가 더 중요 할 수 있지만 섹시 함은 훨씬 적습니다.

  4. ==============================

    4.function () use () {}는 PHP에서 클로저입니다. use를 사용하여 부모 함수의 변수를 포함해야합니다.

    function () use () {}는 PHP에서 클로저입니다. use를 사용하여 부모 함수의 변수를 포함해야합니다.

    <?php
    $message = "hello\n";
    
    
    $example = function () {
        echo $message;
    };
    // Notice: Undefined variable: message
    $example();
    
    
    $example = function () use ($message) {
        echo $message;
    };
    // "hello"
    $example();
    
    
    // Inherited variable's value is from when the function is defined, not when called
    $message = "world\n";
    // "hello"
    $example();
    
    
    // Inherit by-reference
    $message = "hello\n";
    $example = function () use (&$message) {
        echo $message;
    };
    // "hello"
    $example();
    // The changed value in the parent scope is reflected inside the function call
    $message = "world\n";
    // "world"
    $example();
    
    
    // Closures can also accept regular arguments
    $example = function ($arg) use ($message) {
        echo $arg . ' ' . $message;
    };
    // "hello world"
    $example("hello");
    
  5. ==============================

    5.Zupa는 '사용'으로 클로저를 설명하고 EarlyBinding과 'used'변수를 참조하는 것의 차이점을 설명하는 훌륭한 작업을 수행했습니다.

    Zupa는 '사용'으로 클로저를 설명하고 EarlyBinding과 'used'변수를 참조하는 것의 차이점을 설명하는 훌륭한 작업을 수행했습니다.

    그래서 변수의 초기 바인딩 (= 복사)으로 코드 예제를 만들었습니다.

    <?php
    
    $a = 1;
    $b = 2;
    
    $closureExampleEarlyBinding = function() use ($a, $b){
        $a++;
        $b++;
        echo "Inside \$closureExampleEarlyBinding() \$a = ".$a."<br />";
        echo "Inside \$closureExampleEarlyBinding() \$b = ".$b."<br />";    
    };
    
    echo "Before executing \$closureExampleEarlyBinding() \$a = ".$a."<br />";
    echo "Before executing \$closureExampleEarlyBinding() \$b = ".$b."<br />";  
    
    $closureExampleEarlyBinding();
    
    echo "After executing \$closureExampleEarlyBinding() \$a = ".$a."<br />";
    echo "After executing \$closureExampleEarlyBinding() \$b = ".$b."<br />";
    
    /* this will output:
    Before executing $closureExampleEarlyBinding() $a = 1
    Before executing $closureExampleEarlyBinding() $b = 2
    Inside $closureExampleEarlyBinding() $a = 2
    Inside $closureExampleEarlyBinding() $b = 3
    After executing $closureExampleEarlyBinding() $a = 1
    After executing $closureExampleEarlyBinding() $b = 2
    */
    
    ?>
    

    변수를 참조하는 예 (변수 앞에 '&'문자가 있음);

    <?php
    
    $a = 1;
    $b = 2;
    
    $closureExampleReferencing = function() use (&$a, &$b){
        $a++;
        $b++;
        echo "Inside \$closureExampleReferencing() \$a = ".$a."<br />";
        echo "Inside \$closureExampleReferencing() \$b = ".$b."<br />"; 
    };
    
    echo "Before executing \$closureExampleReferencing() \$a = ".$a."<br />";
    echo "Before executing \$closureExampleReferencing() \$b = ".$b."<br />";   
    
    $closureExampleReferencing();
    
    echo "After executing \$closureExampleReferencing() \$a = ".$a."<br />";
    echo "After executing \$closureExampleReferencing() \$b = ".$b."<br />";    
    
    /* this will output:
    Before executing $closureExampleReferencing() $a = 1
    Before executing $closureExampleReferencing() $b = 2
    Inside $closureExampleReferencing() $a = 2
    Inside $closureExampleReferencing() $b = 3
    After executing $closureExampleReferencing() $a = 2
    After executing $closureExampleReferencing() $b = 3
    */
    
    ?>
    
  6. from https://stackoverflow.com/questions/1065188/in-php-what-is-a-closure-and-why-does-it-use-the-the-use-identifier by cc-by-sa and MIT license