7

在 Python 中,您可以拥有以下内容:

def foo(param1, param2):
    def bar():
        print param1 + param2
    bar()

不过,我在 PHP 中的这种行为遇到了一些困难。我希望这可以通过以下方式工作:

function foo($param1, $param2)
{
    function bar()
    {
        echo $param1 + $param2;
    }
    bar();
}

但这失败了。所以我读了一些关于闭包的文章(这不是叫做闭包吗?我知道它是用 Python 编写的)。在关于匿名函数的php 文档中(他们说这些函数被实现为闭包),他们告诉您以下列方式使用 use() 表达式:

function foo($param1, $param2)
{
    function bar() use($param1, $param2)
    {
        echo $param1 + $param2;
    }
    bar();
}

但这仍然失败。所以我把它改成了 PHP 匿名函数,就像这样:

function foo($param1, $param2)
{
    $bar = function() use($param1, $param2)
    {
        echo $param1 + $param2;
    };
    $bar();
}

这确实有效,但它看起来真的很难看。我错过了什么吗?我可以以任何方式改善这一点吗?还是我只需要使用“丑陋”的方式?

(我不是在寻找关于闭包是否有用的讨论)

4

3 回答 3

4

function bar() use($param1, $param2)我在您链接到的手册页上找不到语法,只有有效的“丑陋”版本(真正匿名)。我想你必须使用它。

在您的第二个示例中,bar不是闭包。要在 PHP 中创建闭包,您必须使用丑陋use的或Closure。每个函数都会创建自己的局部作用域,但闭包不是自动的。

正如您在阅读手册时可能注意到的那样,PHP 似乎对术语“闭包”有一个奇怪的定义。他们将其定义为“匿名函数”的同义词:

匿名函数,也称为闭包(...)

令人困惑,对吧?稍后,他们解释说use如果要继承父范围,则需要关键字:

闭包也可以从父作用域继承变量。任何此类变量都必须在函数头中声明。

关于闭包的PHP Wiki rfc 页面为我们提供了一些关于为什么以这种方式实现闭包的提示:

PHP 的范围概念与其他语言定义的范围概念完全不同。将它与变量变量($$var)结合起来,很明显,自动检测外部范围内引用了哪些变量是闭包是不可能的。此外,由于默认情况下全局变量在函数内部都不可见,因此自动使父作用域可用将与 PHP 遵循的当前语言概念相违背。

于 2012-06-01T14:43:51.330 回答
1

在 PHP 中,您无法访问中间范围。您只有本地范围和全局范围。这是 PHP 的不正当范围规则的产物,它与任何理智语言的范围规则完全相反。

于 2012-06-01T14:43:19.347 回答
1

在 PHP 中,命名函数声明 ( function bar ()) 在全局范围内声明一个函数。因此,在您的第一个示例中,当您运行foo函数时,它将bar在全局范围内定义一个函数,然后每个人都可以访问该bar函数,就像您在foo. PHP 中的函数和变量是分开的。命名函数只有一个作用域:全局;虽然您有局部变量,但没有局部范围函数之类的东西。

换句话说,把它放在里面foo是一种错觉;命名函数声明总是全局声明它;把它放在里面foo只会延迟声明运行的时间(因此延迟定义的时间)到foo.

你需要一个闭包。其他答案向您展示了如何做到这一点。

于 2012-06-01T18:14:52.103 回答