speedy-spec/functional

函数原语库。

dev-master 2015-09-03 04:51 UTC

This package is not auto-updated.

Last update: 2024-09-28 18:42:16 UTC


README

Code Climate Test Coverage Build Status Scrutinizer Code Quality

函数原语构成了函数组合的基础,允许使用可重用的组件。

升级策略

该库使用语义版本控制,因此您应该能够升级到支持版本1。版本2可能会支持不同的函数组合方式,使用生成器、协程和其他可用的语言结构。此外,它将应用从使用此库中学到的经验教训,并改进API。后来的主要版本将停止支持PHP5.3。支持PHP5.3的唯一原因是所有代码都能在PHP5.3上运行,并且为了拓宽可以使用此库进行开发的用户数量。

该库支持PHP5.3。其他版本的PHP也得到支持,以便使用其他版本的功能。

安装

您可以使用composer安装此库。

待办事项:需要添加composer配置。

灵感

函数式PHP库

此库受到Lars Strojny 函数式PHP仓库的启发。区别在于函数不会检查任何值是否正确,如果传递的集合不是数组或遍历,则会失败。您将收到通知或警告,您需要在自己的代码中修复这些问题。

验证应该在函数外部进行,并且此库中的函数假设您正在将正确的值作为参数传递。

其他变化是,此库中的代码尽可能重用现有函数。目标是函数组合和减少重复代码。实现这一点最好的方法是尽可能多地重用代码,即使这可能会降低性能。

Laravel数组助手

一些来自Laravel仓库的函数已被移植到此库中。名称将不同,并且与库的其他部分位于同一命名空间下。

可能会有所不同。我将参考网站文档,而不是PHP代码。行为不会完全匹配,但根据文档,至少应该提供类似的行为。

可能将Laravel测试套件中的Laravel助手拉取并复制到此库中,以提供匹配,但我真的不认为这与完全匹配Laravel的函数有很大关系。如果您正在使用Laravel,那么您将使用Laravel的函数。此库是为那些不想拉取Laravel库,但仍想使用类似函数的人准备的。

不会移植同时修改集合并返回数据的函数。该库中的函数可能会修改或访问数据,但不能同时进行。函数还将返回包含修改的集合的副本。原始集合不得通过调用以下任何函数进行修改。

Underscore PHP

为了进一步扩展库,使用了Underscore PHP作为参考。由于一些功能与函数式PHP和Laravel数组助手相匹配,一些函数名称有所不同。

指南目录表

待办事项:需要将此移动到docs目录或网站以进行文档。

集合回调函数

大多数集合回调将包含元素、索引和集合作为参数。

$callback = function($element, $index, $collection) {
	// return after doing something.
};

归约集合回调将有一个额外的参数为当前值。

$callback = function($element, $current, $index, $collection) {
	// return something with element and current.
};

不需要每个参数,建议只使用参数。

删除第一个函数

在回调返回false之前删除集合中的元素。这将从数组的初始部分删除元素。

$values = array(0, 1, 2, 3, 4);

$filtered = \Mimic\Functional\dropFirst($values, function($element) {
	return $element < 2;
});

$filtered将是array(2, 3, 4)

如果数组未排序,则上述内容不会给出所需的结果。

$values = array(2, 0, 1, 3, 4);

$filtered = \Mimic\Functional\dropFirst($values, function($element) {
	return $element < 2;
});

$filtered将是array(2, 0, 1, 3, 4)

删除最后一个函数

在回调返回true之后删除集合中的元素。这将从数组的其余部分删除元素。

$values = array(0, 1, 2, 3, 4);

$filtered = \Mimic\Functional\dropFirst($values, function($element) {
	return $element >= 3;
});

$filtered将是array(0, 1, 2)

每个函数

每个迭代通过每个元素传递到回调,但在迭代完成后不保存任何内容也不返回任何内容。

$values = array(0, 1, 2, 3, 4);

\Mimic\Functional\each($values, function($element) {
	echo $element * $element;
});

// Output: 014916

每个函数

迭代一个集合,检查每个元素是否通过回调。这是none()的相反。

$callback = function($element) {
	return $element === 1;
};

$true = \Mimic\Functional\every(array(1, 1, 1, 1), $callback);
$false = \Mimic\Functional\every(array(1, 2, 1, 1), $callback);

过滤函数

当回调返回true时接受集合中的元素,当回调返回false时丢弃元素。与reject()相反。选择函数select()作为同义词存在。

/** @todo finish example(s) */

第一个和头部函数

在没有回调的情况下检索集合中的第一个元素。

$collection = array(1, 1, 4, 2, 3, 4, 5);

$result = \Mimic\Functional\first($collection);
// $result = 1;
// $index = 0;

$result = \Mimic\Functional\head($collection);
// $result = 1;
// $index = 0;

当有回调时,则应用该回调,并返回回调返回true的第一个元素。

$collection = array(1, 1, 4, 2, 3, 4, 5);

$callback = function($element, $index, $collection) {
	return $element === 4;
};

$result = \Mimic\Functional\first($collection, callback);
// $result = 4;
// $index = 2;

$result = \Mimic\Functional\head($collection, callback);
// $result = 4;
// $index = 2;

第一个索引函数

返回数组中值匹配的第一个索引。

$index = \Mimic\Functional\firstIndexOf(['this', 'is', 'a', 'test'], 'a');
// $index = 2

扁平映射函数

待完成:完成

/** @todo finish example(s) */

压平函数

待完成:完成

/** @todo finish example(s) */

分组函数

待完成:完成

/** @todo finish example(s) */

调用函数

在类上调用方法,如果类上存在该方法。这可以用于实例方法和类方法。它可以用于混合对象,执行会跳过非对象元素或当元素与方法名称参数组合不可调用时。

将参数作为数组传递,以允许更好的组合。这主要是PHP5.3的限制。PHP7或PHP5.6的解决方案可能在未来不需要这样做。

class Example {
	public method test() {
		return func_get_args();
	}

	public static method testStatic() {
		return func_get_args();
	}
}

$instance = new Example;

$collection = array('nothing', $instance, $instance, 'Example', 'Example');

$result = \Mimic\Functional\invoke($collection, 'test');
// $result = array(
//     null,
//     array(),
//     array(),
//     null,
//     null,
// );

$result = \Mimic\Functional\invoke($collection, 'test', array(1));
// $result = array(
//     null,
//     array(1),
//     array(1),
//     null,
//     null,
// );

$result = \Mimic\Functional\invoke($collection, 'testStatic');
// $result = array(
//     null,
//     null,
//     null,
//     array(),
//     array(),
// );

$result = \Mimic\Functional\invoke($collection, 'testStatic', array(1));
// $result = array(
//     null,
//     null,
//     null,
//     array(1),
//     array(1),
// );

调用如果函数

仅在结果可调用时在类上调用方法。您可以设置当给定的参数不可调用时将返回的默认值。传递给回调的参数包含在一个数组中。

class Example {
	public method test() {
		return func_get_args();
	}

	public static method testStatic() {
		return func_get_args();
	}
}

$instance = new Example;

$result = \Mimic\Functional\invokeIf($instance, 'test');
// $result = array();

$result = \Mimic\Functional\invokeIf($instance, 'test', array(1));
// $result = array(1);

$result = \Mimic\Functional\invokeIf($instance, 'denied', array(1));
// $result = null;

$result = \Mimic\Functional\invokeIf($instance, 'denied', array(1), false);
// $result = false;

$result = \Mimic\Functional\invokeIf('Example', 'testStatic');
// $result = array();

$result = \Mimic\Functional\invokeIf('Example', 'testStatic', array(1));
// $result = array(1);

$result = \Mimic\Functional\invokeIf('Example', 'denied', array(1));
// $result = null;

$result = \Mimic\Functional\invokeIf('Example', 'denied', array(1), false);
// $result = false;

调用第一个函数

调用第一个可调用的元素并从该回调返回结果。

class Example1 {
	public method test() {
		return func_get_args();
	}

	public static method testStatic() {
		return func_get_args();
	}
}

class Example2 {
	public method test() {
		return array('example2->test()');
	}

	public static method testStatic() {
		return array('example2::testStatic');
	}
}

$collection = array('nothing', new Example1, new Example2, 'Example1', 'Example2');

$result = \Mimic\Functional\invokeFirst($collection, 'test');
// $result = \Mimic\Functional\value(new Example1)->test();
// $result = array();

$result = \Mimic\Functional\invokeFirst($collection, 'test', array(1));
// $result = \Mimic\Functional\value(new Example1)->test(1);
// $result = array(1);

$result = \Mimic\Functional\invokeFirst($collection, 'testStatic'));
// $result = Example1::testStatic();
// $result = array();

$result = \Mimic\Functional\invokeFirst($collection, 'testStatic', array(1));
// $result = Example1::testStatic(1);
// $result = array(1);

调用最后一个函数

调用最后一个可调用的元素并从该回调返回结果。

class Example1 {
	public method test() {
		return func_get_args();
	}

	public static method testStatic() {
		return func_get_args();
	}
}

class Example2 {
	public method test() {
		return array('example2->test()');
	}

	public static method testStatic() {
		return array('example2::testStatic');
	}
}

$collection = array('nothing', new Example1, new Example2, 'Example1', 'Example2');

$result = \Mimic\Functional\invokeFirst($collection, 'test');
// $result = \Mimic\Functional\value(new Example2)->test();
// $result = array('example2->test()');

$result = \Mimic\Functional\invokeFirst($collection, 'test', array(1));
// $result = \Mimic\Functional\value(new Example2)->test(1);
// $result = array('example2->test()');

$result = \Mimic\Functional\invokeFirst($collection, 'testStatic'));
// $result = Example2::testStatic();
// $result = array('example2::testStatic');

$result = \Mimic\Functional\invokeFirst($collection, 'testStatic', array(1));
// $result = Example2::testStatic(1);
// $result = array('example2::testStatic');

尾函数

在没有提供回调的情况下,检索集合的最后一个元素。

$collection = array(1, 1, 4, 2, 3, 4, 5);

$result = \Mimic\Functional\last($collection);
// $result = 5;
// $index = 6;

$result = \Mimic\Functional\tail($collection);
// $result = 5;
// $index = 6;

如果有传递回调,则返回回调返回为真的最后一个元素。

$collection = array(1, 1, 4, 2, 3, 4, 5);

$callback = function($element, $index, $collection) {
	return $element === 4;
};

$result = \Mimic\Functional\last($collection, callback);
// $result = 4;
// $index = 5;

$result = \Mimic\Functional\tail($collection, callback);
// $result = 4;
// $index = 5;

最后一个索引函数

待完成:完成

/** @todo finish example(s) */

映射函数

Map遍历每个元素,对每个元素应用回调。返回值保存在数组中并返回。

$values = array(0, 1, 2, 3, 4);

$squares = \Mimic\Functional\map($values, function($element) {
	return $element * $element;
});

$squares将包含array(0, 1, 4, 9, 16)

无函数

遍历集合,检查没有元素通过回调。这是every()函数的反面。

$callback = function($element) {
	return $element === 1;
};

$true = \Mimic\Functional\none(array(2, 2, 2, 2), $callback);
$false = \Mimic\Functional\none(array(1, 2, 2, 2), $callback);

分割函数

待完成:完成

/** @todo finish example(s) */

选择函数

待完成:完成

/** @todo finish example(s) */

摘取函数

待完成:完成

/** @todo finish example(s) */

归约函数

遍历集合,在处理所有元素后返回一个单独的值。必须也将初始值作为第二个参数传递。

$values = array(0, 1, 2, 3, 4);

$sum = \Mimic\Functional\reduce($values, 0, function($element, $current) {
	return $current + $element;
});

$sum将是10。

$values = array(0, 1, 2, 3, 4);

$sum = \Mimic\Functional\reduce($values, 5, function($element, $current) {
	return $current + $element;
});

$sum将是15。

归约左函数

待完成:完成

/** @todo finish example(s) */

归约右函数

待完成:完成

/** @todo finish example(s) */

拒绝函数

当回调返回true时拒绝或丢弃元素。与filter()select()相反。

/** @todo finish example(s) */

选择函数

filter()的别名。此函数与filter()的工作方式相同。这存在是为了在语义上是reject()的反面。因此,如果您希望在集合上选择而不是过滤集合,则可以使用此函数。这样,在阅读代码时,拒绝和选择在语义上描述了集合上的过程。

/** @todo finish example(s) */

短函数

短函数会在回调返回true时检查回调并从集合中退出。这在满足条件后需要从集合中退出时非常有用。

您还应该查看dropFirst()dropLast()来从集合中删除元素。

$values = array(0, 1, 2, 3, 4);
$checkValue = 5;

$contains = \Mimic\Functional\reduce($values, true, false, function($element) use ($checkValue) {
	return $element === $checkValue;
});

$contains是false。

$values = array(0, 1, 2, 3, 4);
$checkValue = 2;

$contains = \Mimic\Functional\reduce($values, true, false, function($element) use ($checkValue) {
	return $element === $checkValue;
});

$contains是true。

一些函数

待完成:完成

/** @todo finish example(s) */

排序函数

待完成:完成

/** @todo finish example(s) */

独特函数

待完成:完成

/** @todo finish example(s) */

连接函数

待完成:完成

/** @todo finish example(s) */

辅助函数

辅助函数不接受回调,并提供一种简单的方法来遍历集合,执行特定的任务并返回结果。

比较函数

创建一个用于集合函数的回调,该回调比较集合元素与比较值。可选地测试类型是否也匹配。

$value = 1;
$checkTypeMatches = true;
$callback = \Mimic\Functional\compare($value, $checkTypeMatches);

$false = $callback(0);
$false = $callback('0');

$true = $callback(1);

如果没有严格的检查,它将简单地比较两个值。

$value = 1;
$checkTypeMatches = false;
$callback = \Mimic\Functional\compare($value, $checkTypeMatches);

$false = $callback(0);

$true = $callback(1);
$true = $callback('1');

包含函数

查找是否在集合中存在给定的值。

$values = array('something', 'else', 'here');
$exists = \Mimic\Functional\contains($values, 'else');

if ($exists) {
	echo "Else exists in values.";
}

$exists = \Mimic\Functional\contains($values, 'hello');

if ( ! $exists ) {
	echo "Hello does not exist in values.";
}

您还可以使用严格的检查来确保类型匹配。

$values = array(1, 3, '5');
$exists = \Mimic\Functional\contains($values, 3, true);

if ($exists) {
	echo "3 exists in values.";
}

$exists = \Mimic\Functional\contains($values, 5, true);

if ( ! $exists ) {
	echo "5 integer does not exists in values.";
}

假函数

False函数检查数组中的每个值是否为false。这在与map结合使用时非常有用,其中评估一些条款,然后使用此函数来检查是否每个值都与false相同。

$values = array(1, 3, 5, 7);
$evenEvaluation = \Mimic\Functional\map($values, function($element) {
	return ($element % 2) === 0;
});

$allOdd = \Mimic\Functional\false($evenEvaluation);

if ($allOdd) {
	echo "All values are odd.";
}

假函数

Falsy函数检查数组中的每个值是否评估为false。请注意,某些不是false的值仍然会评估为false。

$values = array(false, 0, '', null);
$allFalsy = \Mimic\Functional\falsy($values);

if ($allFalsy) {
	echo "All values are falsy.";
}

记忆化函数

记忆化(Memoization)是指存储或保存函数调用的结果的过程。这种缓存机制可以快速返回那些可能需要较长时间处理的计算结果。这仅适用于纯函数或对于给定的输入始终返回相同输出的函数。对不具有这种行为的函数进行此操作将会失败。

由记忆化函数返回的闭包与传递给函数的回调具有相同的定义。它只是将回调包装成存储结果并返回原始结果值的机制。考虑到哈希过程,即使在哈希的情况下,也应该只有在仍然有性能提升时才使用。这应该很容易进行比较。不使用记忆化运行性能基准测试,然后使用记忆化运行。如果使用记忆化更快,则应使用它。请注意,每次使用不同参数调用时,都会消耗额外的内存。

$memoizedCallback = \Mimic\Functional\memoize(function($name) {
	echo "Function called!\n";
	return 'hello '. $name;
});

$result = $memoizedCallback('Jacob');

// Output: Function called!
// $result = 'hello Jacob';

// Second call
$result = $memoizedCallback('Jacob');

// Output: (No output from call)
// $result = 'hello Jacob';

也可以通过在返回的对象上调用`clear()`来清除所有结果。

$memoizedCallback = \Mimic\Functional\memoize(function($name) {
	echo "Function called!";
	return 'hello '. $name;
});

$result = $memoizedCallback('Jacob');

// Output: Function called!
// $result = 'hello Jacob';

$memoizedCallback->clear();

$result = $memoizedCallback('Jacob');

// Output: Function called!
// $result = 'hello Jacob';

最后,可以通过将原始参数传递给clean方法来清除单个值的结果。

$memoizedCallback = \Mimic\Functional\memoize(function($name) {
	echo "Function called!";
	return 'hello '. $name;
});

$result = $memoizedCallback('Jacob');

// Output: Function called!
// $result = 'hello Jacob';

$memoizedCallback->clean('Jacob');

$result = $memoizedCallback('Jacob');

// Output: Function called!
// $result = 'hello Jacob';

没有参数时的调用结果也会被缓存。也可以通过调用$memoizedCallback->clean();或调用不带任何参数的clean方法来清除不带参数的调用结果。

警告:目前,记忆化不能传递给库中的其他函数。在发布前将修复此问题。

否定函数

否定传递给回调的任何布尔值。该函数旨在作为集合回调函数传递。

$callback = function($element) {
	return true;
}

$negate = \Mimic\Functional\negate($callback);

if ( ! $negate(1, null, null) ) {
	echo "You shall not pass!"
}

真函数

真函数检查数组中的每个值是否为真。这与map结合使用很有用,其中你评估某个条件,然后使用此函数来检查每个值是否都相同于真。

$values = array(2, 4, 6, 8);
$evenEvaluation = \Mimic\Functional\map($values, function($element) {
	return ($element % 2) === 0;
});

$allEven = \Mimic\Functional\true($evenEvaluation);

if ($allEven) {
	echo "All values are even.";
}

真值函数

真值函数检查数组中的每个值是否评估为真。请注意,某些不是真的值也会评估为真。

$values = array(true, 1, -1, '0', array());
$allTruthy = \Mimic\Functional\truthy($values);

if ($allTruthy) {
	echo "All values are truthy.";
}

值函数

值返回给定的值,除非给值传递了一个回调,那么将返回调用回调(不带参数)的结果。

$zero = \Mimic\Functional\value(0);
$true = \Mimic\Functional\value(true);
$true = \Mimic\Functional\value(function() { return true; });

值函数可以与对象一起使用。请注意,这个快捷方式在PHP 5.4及以后版本中不需要使用。

$object = \Mimic\Functional\value(new Type());

与函数

函数将给定的值传递给回调并返回回调的结果。

$callback = function($value) {
	return ! $value;
};
$false = \Mimic\Functional\with(true, $callback);

$true = \Mimic\Functional\with(false, $callback);

数学函数

接受集合并对其应用某些过程的函数。这些函数不接收回调,是针对包含整数和浮点数的集合的常见数学操作的辅助函数。

这些函数将支持数字字符串、整数和浮点数。你还可以在集合中组合这些类型。

平均值函数

平均值通过基本的PHP操作返回平均值。此函数不使用GMPbcmath扩展。如果你需要更准确的结果,则需要使用另一个函数。

$average = \Mimic\Functional\average(array(0, 1, 2, 3, 4));

$average将是2

$average = \Mimic\Functional\average(array(1.5, 2.5, 2.5, 2.5, 3.5, 4.5));

$average将是2.83333

差值函数

差异返回从初始值减去值的总和。默认值为0,是可选的。

$total = \Mimic\Functional\difference(array(1, 2, 3, 4, 5));

$total将是-15

$total = \Mimic\Functional\difference(array(1, 2, 3, 4, 5), 15);

$total将是0

最大值函数

返回集合中的最大数值。

$max = \Mimic\Functional\maximum(array(1, 2, 3, 4, 5));

$max将是5。

最小值函数

返回集合中的最大数值。

$min = \Mimic\Functional\minimum(array(1, 2, 3, 4, 5));

$min将是1。

乘积函数

乘积返回值的总和乘以初始值。默认值为1,是可选的。传递0(零)将不会执行任何操作,并且当初始值为零时,函数不会退出,从而造成延迟。

$total = \Mimic\Functional\product(array(1, 2, 3, 4, 5));

$total将是120

$total = \Mimic\Functional\product(array(1, 2, 3, 4, 5), 5);

$total将是600

$total = \Mimic\Functional\product(array(1, 2, 3, 0, 4, 5), 1);
$total = \Mimic\Functional\product(array(1, 2, 3, 4, 5, 0), 1);

两次调用的$total都将为0。任何0值都会破坏最终值,并且它总是为零。请执行筛选以删除0值。

除法函数

商返回值是除以初始值的值的总和。默认值是 1,是可选的。传递 0(零)将不会做任何事情,函数也不会在初始值为零时退出,从而产生延迟。

$total = \Mimic\Functional\quotientDivisor(array(5, 10, 100));

$total 将是 50。执行将进行 5 / 110 / 5,最后是 100 / 2 以得到 50

$total = \Mimic\Functional\quotientDivisor(array(2, 4, 10));

$total 将是 5。执行将进行 2 / 14 / 2,最后是 10 / 2 以得到 5

$total = \Mimic\Functional\quotientDivisor(array(1, 2, 3), 5);

$total 将是 0.3。执行将进行 1 / 52 / 0.2,最后是 3 / 10 以得到 0.3

$total = \Mimic\Functional\quotientDivisor(array(1, 2, 3, 0, 4, 5), 1);
$total = \Mimic\Functional\quotientDivisor(array(1, 2, 3, 4, 5, 0), 1);

两次调用的$total都将为0。任何0值都会破坏最终值,并且它总是为零。请执行筛选以删除0值。

quotient() 函数更像是语言处理运算符优先级的方式。这两个函数存在是为了确定如何处理除法。初始值默认不使用。

$total = \Mimic\Functional\quotient(array(100, 10, 5));

$total 将是 2。执行将进行 100 / 10 / 5,结果是 2

$total = \Mimic\Functional\quotient(array(10, 5), 100);

$total 将是 2。执行将进行 100 / 10 / 5,结果是 2

$total = \Mimic\Functional\quotient(array(1, 2, 3, 0, 4, 5), 100);
$total = \Mimic\Functional\quotient(array(1, 2, 3, 4, 5, 0), 100);

将忽略或过滤掉评估中的 0 值。因此,执行将是 100 / 1 / 2 / 3 / 4 / 5,结果是 0.83333333

总和函数

和返回从初始值开始累加的值的总和。默认值是 0,是可选的。

$total = \Mimic\Functional\difference(array(1, 2, 3, 4, 5));

$total 将是 15

$total = \Mimic\Functional\difference(array(1, 2, 3, 4, 5), 15);

$total 将是 30