【问题标题】:PHP 5.3.6 lambda not working?PHP 5.3.6 lambda 不工作?
【发布时间】:2013-01-18 07:42:54
【问题描述】:

以下 PHP 代码导致错误:以“say”开头的行出现意外 T_FUNCTION。我使用的是 PHP 5.3.6 版,因此应该支持 lambda,但它不起作用。我也不知道“use”子句在这种情况下是否有效,但删除它并不能解决问题。我的语法有问题吗?注意:$this->backend 在构造函数中定义为 $this->backend = fopen("bar.txt","w+");

class Foo
{
  private $backend;
  private $commands = array(
        0 => array(
            "say" => function($msg) use($this->backend) { fwrite($this->backend,$msg); }
            )
        );
}

【问题讨论】:

    标签: php lambda closures


    【解决方案1】:

    问题是

      use($this->backend)
    

    $this 在你的类蓝图中还不存在,所以你绝对不能将它指定为这一点。

    您尝试做的事情可能无法在匿名函数中执行,因为它本身不是该类的成员,因此无法获得 $this 变量。

    您可能必须在Foo 的适当成员函数中执行此操作,或者将$this 作为参数传递。

    【讨论】:

    • 正如我在原始问题中所说,删除“use($this->backend)”并不能解决错误。此外,删除 fwrite() 调用以使函数中从未提及 $this 并不能修复错误。感谢您的帮助,但我更关心的是让 lambda 现在完全正常工作的直接问题。
    • @Chris 哦,我误会了,对不起。
    • 没问题,就像我说的感谢关于 $this 的观点,我已经重构了它的特定部分以删除对 $this 的引用,但仍然想摆脱讨厌的“首先是意外的 T_FUNCTION" 错误:)
    • @Chris 嗯,这可能意味着不可能在类蓝图中添加匿名函数作为属性。它看起来非常像。不过,让我们等待专家意见,我不确定...您可以尝试在构造函数中分配它,我敢打赌这会立即起作用
    • @Pekka웃 stackoverflow.com/a/4000540/1283847 对于 lambda 函数也是如此,无论如何在内部它们都是 Closure 类的实例。
    【解决方案2】:

    特定于 PHP 5.3.x

    首先,不能将 lambdas 指定为默认属性值(lambdas 不被视为常量表达式)。因此无法直接进行该分配;您需要在构造函数中执行此操作。

    其次,在 PHP 5.3.x 中,您不能在 lambda 中使用 $this。典型的解决方法是复制$this 并捕获它,如下所示:

    $that = $this;
    $func = function() use($that) { ... };
    

    但是,这种方式根本无法从 lambda 内部访问 $that 的非公共成员,因此该技术不能直接用于您的情况。

    您可能应该做的是将$this->backend 存储在构造函数内部的局部变量中,并将use 存储在lambda 内部的那个变量中。存储和捕获都可以通过值或引用来完成,具体取决于您是否希望任何修改传播到 lambda 之外以及$this->backend 的值在调用 lambda 之前可能会发生变化的可能性:

     public function __construct() {
        $backend = $this->backend;
        $this->commands = array(
            'say' => function($msg) use($backend) { fwrite($backend, $msg); }
        );
     }
    

    以后的 PHP 版本

    从 PHP 5.4.0 开始,您可以在类方法中定义的 lambda 中隐式使用 $this

     public function __construct() {
        $this->commands = array(
            'say' => function($msg) { fwrite($this->backend, $msg); }
        );
     }
    

    lambda 不能作为默认属性值的限制仍然存在。

    【讨论】:

    • 我的 PHP 版本不允许在构造函数中使用 array() 语法,但确实允许 $this->commands[0]["say"] = function($msg) use($backend) { ... },否则就像你写的那样。在添加此信息之前,我准备接受此答案。
    • @ChrisBrowne:那……不可能。失败的 array() 语法到底是什么?
    • 语法$this->commands = array( 0 => array("say" => function($msg) { ... })); 与之前有相同的“unexpected T_FUNCTION”错误
    • @ChrisBrowne:但它在例如 works as given 5.3.10。我不是 101% 确定在 5.3.6 中没有什么不同,但非常接近。您使用的是相同的代码吗?
    • 好的,我会接受,因为这可能是我代码中其他地方的错误,我已经转向更大更好的事情,所以真的不想进一步调查;谢谢:)
    【解决方案3】:

    您不能直接从变量或作为 lambda 定义类中的属性;

    // these are incorrect
    private $foo = $bar
    private $callback = function() ...
    
    // correct
    define("BAR", "The bar!");
    
    class A {
        private $foo = BAR;
        private $commands = array();
        ...
        public function __construct() {
            $this->commands[0] = function() ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-13
      • 2013-04-03
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多