在匿名函数中使用变量,该函数在其他地方定义

Posted

技术标签:

【中文标题】在匿名函数中使用变量,该函数在其他地方定义【英文标题】:Use variables inside an anonymous function, which is defined somewhere else 【发布时间】:2012-12-17 19:33:59 【问题描述】:

php 中使用匿名函数时,您可以通过使用 use() 关键字轻松地使用其范围之外的变量。

在我的例子中,匿名函数已经在某处定义,但稍后(在其他地方)在一个类中调用。

下面这段代码是为了说明这个想法:

<?php

$bla = function ( $var1 ) use ($arg)
        
            echo $var1;
        ;

class MyClass

    private $func;

    public function __construct ( $func )
    
        $this->func = $func;
    

    public function test ( $arg )
    
        $closure =  $this->func;
        $closure ( 'anon func' );
    


$c = new MyClass($bla);
$c->test ( 'anon func' );

我正在做的是创建一个anonymous function 并将其存储在一个变量中。我将该变量传递给一个类的方法,这就是我想要运行 anonymous 函数的地方。

但是我不能使用use() 关键字从method 获取$arg 参数这种方式。因为 anonymous 函数是在 method 之外声明的。

但我确实需要一种方法来从运行匿名函数的方法中获取变量。当匿名函数在其他地方声明时,有没有办法做到这一点..?

【问题讨论】:

将其作为参数传递。 @NiclasLarsson 我不能那样做。因为我需要一种通过referenceanonymous function 中更改参数的方法。我可以通过func_get_argstest() 方法内部轻松获取值。然后在那里将这些值传递给anonymous function,但这样它只会获得copy 的值。我需要给它一个reference 您不能使用引用运算符 (&) 通过引用传递它们吗? @NiclasLarsson 通过引用不会使其改变范围。在 OP 的示例中, $arg 仍将指向全局范围内的 $arg 。我知道 OP 希望闭包使用 $arg 从它执行的范围内,例如MyClass::test($arg)。但也许 OP 可以澄清一下。 【参考方案1】:

FWIW,如果你使用 use reference (php.net ex 3.3) 和一个全局的,丑陋的,因为它使用全局变量,你可以做到这一点,但只是把它放在那里:

<?php
$bla = function ( $var1 ) use (&$arg)
        
            return "var1:$var1, arg:$arg";
        ;

class MyClass

    private $func;

    public function __construct ( $func )
    
        $this->func = $func;
    

    public function test ( $param )
    
        global $arg;
        $arg=$param;
        $closure =  $this->func;
        return  $closure ( 'anon func' );
    


$c = new MyClass($bla);
echo $c->test ( 'bla bla' ); //var1:anon func, arg:bla bla

【讨论】:

【参考方案2】:

use 关键字的意义在于将inherit/close over a particular environment state from the parent scope 插入到闭包中当它被定义时,例如

$foo = 1;

$fn = function() use ($foo) 
    return $foo;
;

$foo = 2;

echo $fn(); // gives 1

如果您希望 $foo 稍后关闭,请稍后定义关闭,或者如果您希望 $foo 始终为当前值 (2),请将 $foo 作为常规参数传递。

【讨论】:

希望我忽略了一些东西。但显然没有其他方法可以将所需的变量作为参数传递。 你应该提到它叫做“词法作用域”。所有现代编程语言都使用词法作用域。

以上是关于在匿名函数中使用变量,该函数在其他地方定义的主要内容,如果未能解决你的问题,请参考以下文章

15_匿名函数和闭包的使用

Erlang匿名函数及函数的高阶应用

揭秘PHP匿名函数

Python-匿名函数

Kotlin函数 ⑤ ( 匿名函数变量类型推断 | 匿名函数参数类型自动推断 | 匿名函数又称为 Lambda 表达式 )

函数细说及匿名函数