具有函数内函数的变量的范围?

时间:2012-06-01 14:29:27

标签: php closures anonymous-function

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

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

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

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

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

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

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

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

这确实有效,但它看起来真的很难看。我错过了什么吗?我可以用任何方式改进吗?或者我只需要使用'丑陋'的方式?

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

3 个答案:

答案 0 :(得分:4)

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

在第二个例子中,bar不是闭包。要在PHP中创建闭包,您必须使用丑陋的useClosure class。每个函数都会创建自己的局部范围,但闭包不是自动的。

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

  

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

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

  

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

PHP Wiki rfc page on closures为我们提供了一些关于闭包实现方式的提示:

  

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

关闭是你需要的。其他答案告诉你如何做到这一点。