mkjpryor/function-utils

PHP 函数工具库

dev-master 2015-03-16 20:31 UTC

This package is not auto-updated.

Last update: 2024-09-28 17:43:39 UTC


README

Build Status Coverage Status

此包提供了一些用于处理函数的简单工具。其目的是提供一些核心能力,以实现更函数式编程风格的编程。

安装

mkjpryor/function-utils 可以通过 Composer 安装

php composer.phar require mkjpryor/function-utils dev-master

可用函数

所有函数都在 Mkjp\FunctionUtils 命名空间中。要将它们导入到您的代码中,请使用 use function 语法(PHP 5.6+)。

_()

返回一个占位符对象,用于与下面的 bind 一起使用。

bind(callable $f, ...$bound)

$f 的前 n 个参数绑定到给定的参数上,返回一个新的函数,该函数接受在调用 $f 之前的其余参数。

在绑定参数时,可以给出一个占位符(见 _()),以表示该参数将在以后给出。

示例

function add($a, $b, $c) { return $a + $b + $c; }

$add = bind('add', 1, _(), 3);

echo $add(2);  // Calls $f(1, 2, 3) and prints 6

compose(...$fns)

返回一个新的函数,该函数是从左到右给定函数的组合,即给定这些函数

function f($x) { /* something */ };
function g($x) { /* something */ };
function h($x) { /* something */ };

$fn = compose('f', 'g', 'h');

以下成立

$fn($x) === h(g(f($x)));

返回的函数将接受与第一个函数一样多的参数。所有其他给定的函数应接受单个参数。

示例

function add($x, $y) { return $x + $y; }
function double($x) { return $x * 2; }

$fn = compose('add', 'double');

// The returned function takes the same arguments as add
echo $fn(1, 2);  // Prints 6

curry(callable $f, $n = -1)

接受多个参数的可调用函数,并将其转换为单参数函数的级联,例如给定一个函数

$f = function($x1, $x2, $x3) { /* something */ };

curry($f) 产生一个新的函数 $g,使得

$g = function($x1) {
    return function($x2) use($x1) {
        return function($x3) use($x1, $x2) {
            return $f($x1, $x2, $x3);
        };
    };
};

默认情况下,curry “curries” 函数的所有 必需 参数。如果给出 $n,则为正好那么多参数创建“函数级联”。这对于可变参数或具有可选参数的函数很有用。

由于 PHP 目前不支持函数调用解引用(例如 $f(1)(2)(3)),这对于风格上的用途有限。然而,具有这种行为的函数(即返回新函数直到所有参数都给出)在函数式编程中很有用(这也是为什么 Haskell 中的所有函数都自动 curried 的原因)。

示例

function add($x, $y, $z) { return $x + $y + $z; }

$curried = curry('add');

// If we had function call dereferencing, this could be written $curried(1)(2)(3)
$tmp = $curried(1);
$tmp = $tmp(2);
echo $tmp(3);  // Prints 6

flip(callable $f)

返回一个新函数,它与 $f 相同,但参数顺序相反。

示例

function div($x, $y) { return $x / $y; }

$flipped = flip('div');

// Both of these print 5
echo div(10, 2);
echo $flipped(2, 10);

id($x)

这是经典的 id 函数。它只是返回其参数。

memoize(callable $f)

返回一个新的函数,该函数缓存对 $f 的调用结果,并返回这些结果而不是调用 $f

因此,$f 对于给定的参数组合仅调用一次。这对于结果计算昂贵但仅依赖于参数的纯函数很有用。

注意: 只有当函数频繁地以相同的参数调用,并且结果的计算时间比序列化参数和查找结果键要长时,才值得缓存函数。在将程序进行性能分析以查看哪些函数可能是缓存候选之前可能很有用。

示例

function factorial($n) {
    if( $n <= 0 ) return 1;
    return $n * factorial($n - 1);
}

$mem_fac = memoize('factorial');

echo $mem_fac(10);  // Prints 3628800
echo $mem_fac(10);  // Prints 3628800, but the result was loaded from cache

n_required_args(callable $f)

使用反射确定可调用的必需参数数量。

这将仅考虑 必需 参数,即可选和可变参数不会对计数做出贡献。

示例

function fun1($a, $b, $c, $d = 1) { return $a + $b + $c + $d; }

echo n_required_args('fun1');  // Prints 3

function fun2(...$args) { return count($args); }

echo n_required_args('fun2');  // Prints 0

trampoline(callable $f)

给定一个以跳跃风格编写的函数,trampoline会返回一个新的函数,当调用该新函数时,会执行跳跃风格的函数(即迭代执行返回thunk的函数,直到结果不再可调用为止)。

这可以用来模拟尾递归而不耗尽栈空间——请参见下面的阶乘的伪递归实现。

示例

// This is the traditional tail-recursive fib, except PHP doesn't have tail-recursion
function fib($n, $n_1 = 0, $n_2 = 1) {
    if( $n === 0 ) return $n_1;
    return fib($n - 1, $n_2, $n_1 + $n_2);
};

// This is the trampolined version
function fib_trampoline($n, $n_1 = 0, $n_2 = 1) {
    if( $n === 0 ) return $n_1;
    return function() use($n, $n_1, $n_2) {
        return fib_trampoline($n - 1, $n_2, $n_1 + $n_2);
    };
}

$fib_trampoline = trampoline('fib_trampoline');

echo fib(10);              // Prints 55
echo $fib_trampoline(10);  // Prints 55

echo fib(200);              // BLOWS THE STACK!
echo $fib_trampoline(200);  // Prints 2.8057117299251E+41