【问题标题】:Difference between a lambda function and a closure (in PHP)?lambda 函数和闭包(在 PHP 中)之间的区别?
【发布时间】:2013-11-24 17:16:15
【问题描述】:

“Magento PHP 开发人员指南”第 2 章指出:

Zend Framework 2 使用 100% 面向对象的代码并利用大部分 PHP 5.3 的新特性,即命名空间、后期静态绑定、 lambda 函数和闭包。

虽然What is the difference between a 'closure' and a 'lambda'? 的帖子有一些答案(例如,lambda 只是一个匿名函数,而闭包是一个可以访问不在其参数列表中的变量的函数),但似乎特定于 Python编程语言(其中提到了 Scheme 编程语言)。 例如,根据帖子,在 Python 中,似乎可以有不是 lambda 的闭包,也可以有不是闭包的 lambda。

但是,我对 PHP 编程语言感兴趣,而不是 Python。下面的答案之一似乎指出,在 PHP 中,所有闭包都是 lambda,这与与 Python 状态相关的帖子相冲突。

在我看来,这些概念的细节因语言而异,我对 PHP 很感兴趣,因此发了这篇文章。

所有这些都令人困惑。虽然我认为 lambda 函数通常只是未命名的函数,但以下 Wikipedia 文章更多地介绍了闭包:

http://en.wikipedia.org/wiki/Closure_%28computer_science%29

虽然在 PHP 中没有示例。

【问题讨论】:

标签: php lambda closures php-closures


【解决方案1】:

闭包是 php 中的一个 lambda 函数,它封装了变量,因此一旦它们的原始引用超出范围,就可以使用它们。

闭包是 lambda 函数,但 lambda 函数不是闭包,除非您指定 use 关键字。

这是一个更好的答案:https://stackoverflow.com/a/220728/1152375

【讨论】:

  • 谢谢。我发现有一个通用的答案。在那个线程中写的是 lambda 函数只是一个匿名函数,而闭包是访问可以在函数外部找到的变量的任何函数(这与您上面的答案不匹配,即每个闭包都是一个 lambda 函数,因为根据前面提到的线程,闭包可以有一个名称,只要它访问全局范围)。
  • 这对 PHP 是否正确?我想每种语言都以稍微不同的方式定义这些概念,而我的问题是针对 PHP 的。 PHP中这些的确切定义是什么?谢谢。
  • @JohnSonderson:“闭包”和“匿名函数”的概念与语言无关
  • @newacct 概念和实现可以是两个不同的东西。例如PHP函数不能自动访问全局作用域的环境,PHP手册在php.net/manual/en/class.closure.php的第一行专门定义闭包对象类型为“匿名函数”
  • PHP 实现闭包的另一个重要区别是,默认情况下提供给函数的环境不是由引用变量构成的。 wiki.php.net/rfc/closures#references_vs_copies
【解决方案2】:

有一篇PHP专用的文章有详细的解释和代码示例: http://www.ibm.com/developerworks/library/os-php-5.3new2/

断开链接警告:截至 2014 年 10 月 18 日,上述链接为 404。 我从谷歌缓存中复制了这篇文章并放在here

如果您发现原始文档在任何地方重新出现,请告诉我。

【讨论】:

  • 文章原链接又出现了。
【解决方案3】:

闭包实际上意味着如果你use一个变量,它的值将在一个封闭的函数内使用,而不是在它之外更新它的值。如果您想更新已使用变量的值但作为普通参数,则必须使用引用运算符 &

这就是它的强大用途,您可以在没有依赖全局命名空间的常规函数​​的情况下更轻松地增加/递减类似的东西或创建斐波那契或迭代生成器函数。

Lambda 不支持use,因此它们不能包含外部范围的变量。闭包也可以被缓存,因此它提高了编译性能。

【讨论】:

    【解决方案4】:

    Lambda 函数被分配给一个变量或作为参数传递给另一个函数。闭包使用范围之外的变量。

    使用 lambdas

    因为函数没有名字,你不能像普通函数那样调用它。相反,您必须将其分配给变量或将其作为参数传递给另一个函数。

    // Anonymous function
    // assigned to variable
    $greeting = function () {
      return "Hello world";
    }
    
    // Call function
    echo $greeting();
    // Returns "Hello world"
    

    为了使用匿名函数,我们将它分配给一个变量,然后将该变量作为函数调用。

    您也可以将函数传递给另一个函数,如下所示:

    // Pass Lambda to function
    function shout ($message){
      echo $message();
    }
    
    // Call function
    shout(function(){
      return "Hello world";
    });
    

    什么是闭包?

    闭包本质上与 Lambda 相同,只是它可以访问其创建范围之外的变量。

    例如:

    // Create a user
    $user = "Philip";
    
    // Create a Closure
    $greeting = function() use ($user) {
      echo "Hello $user";
    };
    
    // Greet the user
    $greeting(); // Returns "Hello Philip"
    

    正如您在上面看到的,闭包能够访问$user 变量,因为它是在闭包函数定义的 use 子句中声明的。

    如果您要更改闭包中的$user 变量,它不会影响原始变量。要更新原始变量,我们可以附加一个 & 符号。变量前的 & 表示这是一个引用,因此也会更新原始变量。

    For example:
    // Set counter
    $i = 0;
    // Increase counter within the scope
    // of the function
    $closure = function () use ($i){ $i++; };
    // Run the function
    $closure();
    // The global count hasn't changed
    echo $i; // Returns 0
    
    // Reset count
    $i = 0;
    // Increase counter within the scope
    // of the function but pass it as a reference
    $closure = function () use (&$i){ $i++; };
    // Run the function
    $closure();
    // The global count has increased
    echo $i; // Returns 1
    

    本文是 Philip Brown 文章的一部分,位于 >> culttt.com。您可以在此处找到更多示例。

    【讨论】:

      【解决方案5】:

      功能

      • 一段代码以参数的形式接受一个或多个输入,进行一些处理并返回一个值。
      • 它应该有一个名字,需要时可以用它的名字来调用。
      • 可以将多个函数包装在一个类中(以允许拥有多个同名的函数等等)。

      匿名函数

      • 一个没有名字的函数。
      • 不一定需要创建闭包。

      Lambda

      • 可以分配给变量或作为参数传递给其他函数的匿名函数。
      • 它不能像普通函数一样被调用,因为它没有名称,它必须要么将它分配给一个变量,要么将它作为参数传递给另一个函数。因此它变成了一个 Lambda 函数。
      • 它很有用,因为它们是一种一次性功能,您可以只在某个地方使用一次,而无需在许多地方重复使用它。

      关闭

      • 与 Lambda 相同。但它可以在不使用全局变量的情况下从外部范围访问变量。 (它可以捕捉周围环境的状态)。
      • 可以使用“use”语法以简洁的方式解决变量范围限制。 (基本上它是一个使用 use 语法的匿名函数)。
      • 它不仅是为匿名函数创建的。
      • 它比 Lambda 更智能,因为它能够与来自外部环境的变量进行交互。

            

      【讨论】:

        猜你喜欢
        • 2011-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-11
        • 2011-01-09
        • 2020-06-04
        • 1970-01-01
        • 2022-12-09
        相关资源
        最近更新 更多