php reduce,一个让PHP小白百思不得其解的匿名函数及array_reduce的问题

那么久了还没人回答.我来回答一下吧.

首先是这样的.我们看下面的代码来理解一下

function myfunction($v1,$v2)

{

return $v1+$v2;

}

$a=array(10,15,20);

print_r(array_reduce($a,"myfunction",5)); //50

?>

上面的结果为50.那么它的过程是怎么样的呢?我们对代码进行改良

function myfunction($v1, $v2)

{

var_dump($v1, $v2);

return $v1 + $v2;

}

$a = array(10, 15, 20);

print_r(array_reduce($a, "myfunction", 5)); //50

echo "\n";

然后可以看到如下输出

int(5)

int(10)

int(15)

int(15)

int(30)

int(20)

50

第一个v1 = 5,v2 = 10;

第二个v1 = 15 (前一个返回的值) , v2 = 15; $a[1]的值;

第三个v1 = 30 (上一次的返回值) , v2 = 20; $a[2]的值;

最后输出50. 那么我们看第一个值为什么是5? 因为array_reduce接收的第3个参数就是表示当第一次迭代的时候传递的值。下面我们来自己实现一个array_reduce去深度的理解它 :)

function myfunction($v1, $v2)

{

var_dump($v1, $v2);

return $v1 + $v2;

}

$a = array(10, 15, 20);

print_r(my_array_reduce($a, "myfunction", 5)); //50

echo "\n";

/**

* array_reduce

* @param array $arr

* @param callable $fn

* @param null $initial

* @return mixed

*/

function my_array_reduce(array $arr, callable $fn, $initial = null)

{

$v = $initial;

foreach ($arr as $item) {

$v = $fn($v, $item);

}

return $v;

}

这样是不是好多了呢?

下面是根据题主的问题进行补充

$arr = [

'VerifyCsrfToken'

];

function getSlice()

{

return function($stack, $pipe)

{

return function() use ($stack, $pipe)

{

return $pipe::handle($stack);

};

};

}

$firstSlice = function() {

echo "(6)请求向路由器传递,返回响应.".'
';

};

$go = array_reduce($pipes, getSlice(),$firstSlice);

$go();

当arr 是上面的数组 以及回调的方法是上面的方法时.我们来看看发生了什么

首先

1.getSlice的返回值是function

当arr第一次循环的时候,根据我们上面所提到的array_reduce的原理看看发生了什么?

$arr = [

'VerifyCsrfToken'

];

function getSlice()

{

return function($stack, $pipe)

{

return function() use ($stack, $pipe)

{

return $pipe::handle($stack);

};

};

}

首先看这里

$go = array_reduce($pipes, getSlice(),$firstSlice);

第二个参数传的并不是callback 而是 直接写的 getSlice(); 那么这个函数将会直接执行并且将返回值传递给 array_reduce的第二个参数.

也就是直接返回

function ($stack, $pipe) {

return function () use ($stack, $pipe) {

return $pipe::handle($stack);

};

};

也就是和下面的写法是等价的。

function getSlice($stack, $pipe)

{

return function () use ($stack, $pipe) {

return $pipe::handle($stack);

};

}

$firstSlice = function () {

echo "(6)请求向路由器传递,返回响应\n";

};

$go = my_array_reduce($pipes, "getSlice", $firstSlice);

$go();

只是因为前者的写法更加优雅 易于让ide查找;

弄清楚了这个我们接下来继续看。

return function () use ($stack, $pipe) {

return $pipe::handle($stack);

};

当第一次迭代的时候 $stack 的值为$firstSlice

pipe 的值 为 VerifyCsrfToken.

那么这个函数被执行了.$firstSlice当作参数。

所以当调用$go();时

所有的pipe::handle方法会立即执行。

而每次都把$stack作为参数

所以执行顺序是倒过来了。因为到最后一次的时候 $next 才 === $firstSlice

$pipes = [

"VerifyCsrfToken",

"VerifyCsrfToken1"

];

/**

* array_reduce

* @param array $arr

* @param callable $fn

* @param null $initial

* @return mixed

*/

function my_array_reduce($arr, callable $fn, $initial = null)

{

$v = $initial;

foreach ($arr as $item) {

$v = $fn($v, $item);

}

return $v;

}

再来回顾这段代码.为什么VerifyCsrfToken1先执行呢?

因为当foreach执行完毕的时候. $item = $pipes[count($pipes)-1];

也就是最后一个而 $v 永远为上一个return 的 值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值