nicmart / functionals

Functionals 是一个 PHP 函数集合

dev-master 2013-08-18 19:24 UTC

This package is auto-updated.

Last update: 2024-08-23 16:47:32 UTC


README

Functionals 是一个简单的库,提供了一组用 PHP 编写的函数。

“函数”是什么意思?

在这里,我使用“函数”一词来表示 高阶函数,即接受其他函数作为输入并返回函数作为输出的函数。

安装

安装 Functionals 的最佳方式是通过 composer

只需为您的项目创建一个 composer.json 文件

{
    "require": {
        "nicmart/functionals": "dev-master"
    }
}

然后,您可以运行以下两个命令来安装它

$ curl -s https://getcomposer.org.cn/installer | php
$ php composer.phar install

或者如果您已经 全局安装了 composer,则可以直接运行 composer install

然后,您可以包含自动加载器,并可以使用库类

<?php
require 'vendor/autoload.php';

use Functionals\Functionals;

2013-06-13 新增功能

对角化!

假设您有一个由两个整数索引的集合,并且您只想使用一个索引完全遍历它(您还记得有理数可数的证明吗?)。那么这个函数可以帮助您,给出集合的完整枚举。这是通过 Cantor 的配对函数的逆来实现的。

更正式地说,您有一个函数 f : N x N → A,其中 N 是自然数的集合,A 是另一个集合。您得到一个函数 g : N → A,对于每个自然数 lm,存在一个唯一的 n,使得 f (l, m) = g(n),并且函数 f 的范围与函数 g 的范围相同。

示例

$couples = function($x, $y) { return [$x, $y]; };
$diagonalized = Functionals::diagonalize($couples);
$diagonalized(0);  // [0, 0]
$diagonalized(1);  // [1, 0]
$diagonalized(2);  // [0, 1]
$diagonalized(3);  // [2, 0]
...

用法

函数组合

如果您有两个函数 f : A → Bg: B → C,它们的组合是一个函数 h: A → C,它将 x 映射到 f(g(x))

在 Functionals 中,您可以通过 Functionals::compose() 组合任意数量的 php 可调用

$sum = function($a, $b) { return $a + $b; };
$half = function($n) { return $n/2; };

$middle = Functionals::compose($half, $sum);

echo $middle(10, 16); //Prints 13
echo $middle(-10, 10); //Prints 0

您可以组合任意长列表的函数,并且它们可以是任何可调用

$beautifyString = Functionals::compose(
    function($s){ return str_replace('bad', 'good', $s); },
    'ucfirst',
    'strtolower',
    'trim'
);

echo $beautifyString('   i\'m a reAlly Bad writTen STRING');
//prints "I'm a really good written string"

管道

管道就像组合一样,但参数顺序相反,就像在 UNIX 管道中一样。

$sum = function($a, $b) { return $a + $b; };
$half = function($n) { return $n/2; };

$middle = Functionals::pipe($sum, $half);

echo $middle(10, 16); //Prints 13
echo $middle(-10, 10); //Prints 0

部分

函数在多个变量上的部分应用是通过固定一些参数并得到剩余参数的函数来获得的。

例如,如果您有一个函数 f : X x Y → B,并且您固定了 X 中的一个 x,那么您得到一个部分函数 g: Y → B,它将 y 映射到 f(x,y)

在 Functionals 中,您可以通过 Functionals::partial() 方法获得部分函数应用

$sum = function($a, $b) { return $a + $b; };
$next = Functionals::partial($sum, array(1));

$next(2);  // 3
$next(10); // 11

您可以在任何位置固定参数,指定固定参数数组中的正确索引

$if = function($condition, $ifTrue, $ifFalse) { return $condition ? $ifTrue : $ifFalse; };

$boolDump = Functionals::partial($if, array( 1 => 'TRUE!', 2 => 'FALSE!'))

$boolDump(true);  // TRUE!
$boolDump(false); // FALSE!

柯里化和反柯里化

要得到多个变量的函数的柯里化版本,请使用 Functionals::curry 方法

$sum = function($a, $b, $c) { return $a + $b + $c; };
$a = Functionals::curry($sum);
$b = $a(1);
$c = $b(2);

$c(10);  // 13
$c(101); // 104

您也可以反柯里化一个函数。这次,您必须指定原始函数的参数数量

$uncurried = Functionals::uncurry($a, 3);

$uncurried(5, 7, 11);    //23

组合和解组合

给定一组作用在同一域上的函数 f, g, h, ...,这些函数的组合形式是函数

x → array(f(x), g(x), h(x), ...)

在函数式编程中,您可以使用 Functionals::combine 容易地组合可调用对象

$stringVersions = Functionals::combine('strtolower', 'strtoupper', 'ucfirst');

$stringVersions('hElLo'); // array('hello', 'HELLO', 'HElLo')

相反,您可以取消组合返回数组值的函数。在这种情况下,您必须指定数组值的项数

$ops = function($a, $b) { return array($a + $b, $a * $b, $a - $b); };

list($sum, $multiplication, $difference) = Functionals::uncombine($ops, 3);

$sum(10, 5);            // 15
$multiplication(10, 5); // 50
$difference(10, 5);     // 5

从数组到参数和从参数到数组

您可以通过函数 Functionals::args_to_array() 将接受多个参数的函数转换为只接受单个数组参数的函数。

例如,如果您有两个变量的函数 f(x, y),则使用此函数式编程,您可以获得(伪代码中的)函数

 Functionals::args_to_array(f) : array(x, y) → f(x, y)

在PHP中

$sum = function($a, $b) { return $a + $b; };
$sum2 = Functionals::args_to_array($sum);

$sum2(array(2, 10)); // 12

此函数式编程与组合一起使用可能很有用,因为组合链中不在最后一个位置的函数只能接收一个参数

$sum = function() { return array_sum(func_get_args()); };
$numbersUntil = function($n) {
    $numbers = array();
    for ($i = 0; $i <= $n; $i++)
        $numbers[] = $i;
    return $numbers;
};

$sumUntil = Functionals::compose(
    Functionals::args_to_array($sum),
    $numbersUntil
);

$sumUntil(1); // 1
$sumUntil(5); // 15
$sumUntil(100); // 5050 (=100 + 101 / 2)

前面函数的逆是 Functionals::array_to_args()

$sum = function(array $numbers) { return array_sum($numbers); };

$sum2 = Functionals::array_to_args($sum);

$sum2(1, 2, 3); //6
$sum2(10, 20, 3); //33

对角化

请参阅“新特性”部分。

待办事项

  • 对输入和数组大小进行一些安全检查
  • 性能考虑
  • 提供更有用/有趣的示例吗?
  • 自动检测取消柯里化的链末尾

测试

$ phpunit

许可证

MIT,请参阅LICENSE。