在PHP中的柯里化

huangapple go评论67阅读模式
英文:

Currying in PHP

问题

给定的问题中,你试图在PHP中实现currying(类似于JavaScript中的方式)。你的代码出现了问题,错误信息显示为undefined variable $curried。你的问题是如何递归调用相同的curried函数。期望的输出应该是60,就像在回调函数fn($x, $y, $z) => $x + $y + $z中一样。

英文:

I am trying to implement currying in PHP this time(just like how we do in Javascript). Below is my code which is not working:

<?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);

Issue:

It is giving me undefined variable $curried as you can see here.

Question:

How can we recursively call the same curried function as I see no way to achieve this here?

Expected output:

The expected output should be 60 as done in the callback fn($x, $y, $z) => $x + $y + $z

答案1

得分: 1

Sure, here's the translated content:

好的,这对我来说是一个相当有趣的问题。柯里化具有良好的语法糖以及其他几个优点(比如在日志记录中,我们可以在多个DEBUG/INFO日志语句方法调用中缓存日期时间,而无需为每个日志语句传递日期时间参数)。

  • 首先,在新的匿名回调内递归调用时,$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";

在线演示

英文:

Ok, this has been a pretty interesting problem for me. Currying has a good syntatic sugar along with several other advantages(like in logging, we can cache the datetime across multiple DEBUG/INFO log statement method calls without having the need to pass datetime parameter for each log statement).


  • First, $curried is not accessible when called recursively inside the new anonymous callback. For this to work, we need to pass in this variable in use parameters by reference.

  • Second, we don't seem to have any advantage of calculating the parameter count outside the callback. So, we put this inside the callback.

  • Third, in $curried(array_merge($currArgs, $currArgs2)) , I wasn't passing them as variable length arguments which was causing the problem in parameter count computation. So, fix is $curried(...array_merge($currArgs, $currArgs2)).

Final Working code:

&lt;?php

function test(callable $fn){
    
    $curried =  function(...$currArgs) use(&amp;$fn, &amp;$curried){
        
        $reflection = new ReflectionFunction($fn);
        $args = count($reflection-&gt;getParameters());
        
        if(count($currArgs) == $args){
            return $fn(...$currArgs);
        }else{
            return function(...$currArgs2) use( $fn, $currArgs, &amp;$curried){
                return $curried(...array_merge($currArgs, $currArgs2));
            };
        }
    };
    
    return $curried;
}

$c = test(fn($x, $y, $z) =&gt; $x + $y + $z);

echo $c(10)(20,30),&quot;\n&quot;;
echo $c(10,20)(30),&quot;\n&quot;;
echo $c(10,20,30),&quot;\n&quot;;

Online Demo

huangapple
  • 本文由 发表于 2023年5月10日 16:06:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76216197.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定