baethon/union

PHP的联合类型

v1.0.0 2018-08-17 13:33 UTC

This package is auto-updated.

Last update: 2024-09-24 22:21:27 UTC


README

提供定义标记联合的实用工具。

标记联合是什么?

我不是很擅长用语言表达,但来自Folktale的人描述得很好。

从性能到正确性再到安全性,建模数据都有很多重要原因。标记联合为你提供了一种建模选择的方式,它强制正确处理它们,而不同于基于谓词的分支,例如if语句和其他常见的控制流结构。

安装

composer require baethon/union

使用方法

要创建标记联合,需要创建一个扩展Baethon\Union\AbstractUnion的类。

class Maybe extends \Baethon\Union\AbstractUnion
{
}

还需要定义标签,这些标签将表示联合的状态。

class Maybe extends \Baethon\Union\AbstractUnion
{
	const SOME = 'Some:x';

	const NONE = 'None';
}

签名

每个标签都有一个定义(称为签名),可以使用以下语法定义

{Name}[:[param1[, param2[, ...[, paramN]]]]]

参数定义一个标签是否将持有任何值(称为参数)。它们是可选的。

联合的处理

可以使用静态构造函数调用联合。

$some = Maybe::Some(1);

要处理联合的状态,应使用matchWith()。它将返回匹配回调返回的值

function addTen(Maybe $maybe) {
	return $maybe->matchWith([
		'Some' => function ($x) {
			return $x + 10;
		},
		'None' => function () {
			throw new \Exception('Sorry, can\'t add a number to nothing');
		}
	]);
}

addTen($some); // 11

matchWith()将检查是否映射了所有可能的分支

  • 如果某个标签未被映射,将抛出UnderflowException
  • 如果映射覆盖了比定义的更多的标签,将抛出'OverflowException'。

可以使用通配符映射来覆盖所有其他情况

$some->matchWith([
	'*' => function () {
		return 100;
	}
]); // 100

可以在映射中使用定义的常量值

$some->matchWith([
	Maybe::SOME => function () {},
	Maybe::NONE => function () {}
]);

测试

./vendor/bin/phpunit