在 php 7.4 中重写匿名函数

Rewriting an anonymous function in php 7.4

提问人:wnull 提问时间:11/16/2019 最后编辑:Dharmanwnull 更新时间:9/15/2021 访问量:1534

问:

有以下匿名递归函数:

$f = function($n) use (&$f) {
    return ($n == 1) ? 1 : $n * $f($n - 1);
};

echo $f(5); // 120

我尝试重写到 7.4 版,但出现错误,请告诉我我错过了什么?

$f = fn($n) => ($n == 1) ? 1 : $n * $f($n - 1);
echo $f(5);

注意:未定义的变量:f

致命错误:未捕获错误:函数名称必须为字符串

PHP 闭包 匿名 箭头函数 php-7.4

评论

0赞 Dharman 11/16/2019
这回答了你的问题吗?如何在PHP中使用箭头函数?
0赞 Barmar 11/16/2019
您需要修饰符,以便可以引用外部变量。use()$f
0赞 Dharman 11/16/2019
我不知道这是否应该作为 dup 关闭或回答,所以我非常感谢您的反馈。如果有帮助,请标记为已接受。还有这个帖子:stackoverflow.com/a/56658110/1839439
1赞 Barmar 11/16/2019
如链接问题中所述,箭头函数将按值捕获外部变量。但原来的匿名功能是通过引用捕获的。我不认为箭头函数有等价物。
0赞 wnull 11/16/2019
@Barmar,也就是说,没有它就不可能在新语法中使用?use()

答:

4赞 Barmar 11/16/2019 #1

我认为您不能将函数重写为箭头函数。

箭头函数将在创建函数时按值捕获任何外部变量的。但在创建函数并分配变量之前不会有值。$f

最初的匿名函数通过捕获对变量的引用来解决此问题,而不是 。这样,它将能够使用赋值生成的变量的更新值。use (&$f)use ($f)

评论

0赞 wnull 11/16/2019
谢谢你的解释。可惜,有没有可能认为是箭头的功能缺陷?希望很快任何事情都会成功。
0赞 Barmar 11/16/2019
箭头函数是匿名函数的简化。
15赞 Dharman 11/16/2019 #2

就像 Barmar 说的,你不能从外部范围使用,因为隐式绑定何时发生仍然是未定义的。$f$f

没有什么能阻止您稍后将其作为参数传递。

$f = fn($f, $n) => $n == 1 ? 1 : $n * $f($f, $n - 1);
echo $f($f, 5); // 120

箭头函数的工作方式是,在定义期间,它们将使用外部作用域变量的按值绑定。

如前所述,箭头函数使用按值变量绑定。这大致相当于对箭头函数中使用的每个变量执行 a。- https://wiki.php.net/rfc/arrow_functions_v2use($x)$x

闭包对变量的赋值发生在闭包定义之后,而变量在闭包定义之前是未定义的。$f$f

据我所知,在定义箭头函数时,没有任何机制可以通过引用进行绑定。

2赞 Rain 1/10/2020 #3

我想我刚刚找到了合法(不?$GLOBALS

$f = fn ($n) =>($n == 1) ? 1 : $n * $GLOBALS['f']($n - 1);
echo $f(5); // 120

旁注:如果?$n < 1

评论

0赞 wnull 1/10/2020
哦,我的上帝,这是一个疯狂的想法。
0赞 wnull 1/10/2020
我的问题没有。谢谢你的回答:)n < 1
0赞 Rain 1/10/2020
@Theartofbeingalive我知道,但是如果有人将 0 或负数传递给函数,该函数将永远调用自己。$f(0)
0赞 wnull 1/10/2020
这不应该发生,因为当值为零时使用此函数没有意义。如果该值趋于1,则该函数将为其提供相同的值。
0赞 Rain 1/10/2020
@Theartofbeingalive 这其实是有道理的。因为 AFAIK 这是一个阶乘函数,阶乘等于0!1
2赞 Dawid Dahl 9/13/2021 #4

作为@scorpion35所说的略有变化,您也可以应用咖喱:

$f = fn($f) => fn($x) => $x <= 1 
    ? $x 
    : $f($f)($x-1) * $x;
    
$factorial = $f($f);

$factorial(7); //5040