提问人:Vivek 提问时间:5/10/2023 更新时间:5/11/2023 访问量:81
PHP中的咖喱
Currying in PHP
问:
这次我正在尝试在 PHP 中实现 currying
(就像我们在 Javascript 中所做的那样)。以下是我的代码,它不起作用:
<?php
function test(callable $fn){
$reflection = new ReflectionFunction($fn);
$args = count($reflection->getParameters());
$curried = function(...$currArgs) use($args, $fn){
if(count($currArgs) == $args){
return $fn(...$currArgs);
}else{
return function(...$currArgs2) use($args, $fn, $currArgs){
return $curried(array_merge($currArgs, $currArgs2));
};
}
};
return $curried;
}
$c = test(fn($x, $y, $z) => $x + $y + $z);
echo $c(10)(20,30);
问题:
正如你在这里
看到的,它给了我未定义的变量。$curried
问题:
我们如何递归调用相同的 curried 函数,因为我认为这里没有办法实现这一点?
预期输出:
预期的输出应与回调中一样60
fn($x, $y, $z) => $x + $y + $z
答:
1赞
Vivek
5/11/2023
#1
好吧,这对我来说是一个非常有趣的问题。Currying 具有良好的合成糖以及其他一些优点(例如在日志记录中,我们可以在多个 DEBUG/INFO 日志语句方法调用中缓存日期时间,而无需为每个日志语句传递 datetime 参数)。
首先,在新的匿名回调中以递归方式调用时不可访问。为此,我们需要通过引用在参数中传入此变量。
$curried
use
其次,在回调之外计算参数计数似乎没有任何优势。因此,我们将其放在回调中。
第三,在 中,我没有将它们作为可变长度参数传递,这导致了参数计数计算中的问题。所以,修复是.
$curried(array_merge($currArgs, $currArgs2))
$curried(...array_merge($currArgs, $currArgs2))
最终工作代码:
<?php
function test(callable $fn){
$curried = function(...$currArgs) use(&$fn, &$curried){
$reflection = new ReflectionFunction($fn);
$args = count($reflection->getParameters());
if(count($currArgs) == $args){
return $fn(...$currArgs);
}else{
return function(...$currArgs2) use( $fn, $currArgs, &$curried){
return $curried(...array_merge($currArgs, $currArgs2));
};
}
};
return $curried;
}
$c = test(fn($x, $y, $z) => $x + $y + $z);
echo $c(10)(20,30),"\n";
echo $c(10,20)(30),"\n";
echo $c(10,20,30),"\n";
评论
这个答案
看起来很接近,但我假设匿名函数的词法范围内的局部变量一旦函数调用退出就会被销毁,这与 Javascript 不同,因为变量会保持活动状态,直到不再调用内部匿名函数并且垃圾收集器履行其职责。