pwm/tc

类型安全的集合。

这个包的官方仓库似乎已经不存在,因此该包已被冻结。

1.1.0 2018-05-16 09:04 UTC

This package is auto-updated.

Last update: 2023-04-28 22:59:13 UTC


README

Build Status codecov Maintainability Test Coverage License: MIT

TypedCollection 是一个简单的抽象集合类,在创建时会检查其元素类型,确保集合的类型安全。

使用 TypedCollection 创建的集合是不可变的、可迭代的、可计数的和可列出的。如果您需要一个可变容器,可以简单地子类化它并添加相关修改器。

该库包含一些具体的实现,例如:Bool、Callable、Float、Int 和 String 集合,但使用任何自定义类型实现自己的自定义类型集合是微不足道的。

目录

原因

随着 PHP7 的出现,该语言开始在一定程度上支持类型声明,因此我们终于可以编写如下代码

function isEven(int $x): bool {
    return $x % 2 === 0;
}

其中 $x 作为返回类型是 bool,因此保证 $x 是一个 int。另一方面,我们仍然不能说像我们想要获取一个整数列表这样的事情,即。

function sum(int[] $xs): int { // can't write int[], only array
    return array_sum($xs);
}

不是有效的 PHP 语法。我们只能在这里使用 array 作为类型声明,因此像 sum([1, 'a', false]) 这样的不合理情况无法被类型检查器捕获。

将上述内容进一步扩展,我们只想保证列表的元素是特定类型的,而不管实际类型是什么。这听起来可能有些奇怪,所以这里有一个例子

$addOne = function (int $x): int { return $x + 1; };
$toUpper = function (string $s): string { return strtoupper($s); };

array_map($addOne, [1, 2, 3]); // [2, 3, 4]
array_map($toUpper, ['a', 'b', 'c']); // ['A', 'B', 'C']

Map 不关心其函数参数的类型,也不关心其列表元素的类型。它只关心两件事

  • 列表的元素都是同一种类型
  • 这种类型与其函数参数的类型相同

使用 PHP 的 array,我们无法保证这两点。使用 TypedCollection,我们可以保证第一点

function map(callable $f, TypedCollection $c) {
    return array_map($f, $c->toList());
}

保证了 $c 的元素都是同一类型,即。

map($addOne, new IntCollection(1, 2, 3)); // [2, 3, 4]
map($toUpper, new StringCollection('a', 'b', 'c')); // ['A', 'B', 'C']

但是

map($addOne, new IntCollection(1, 'a', false)); // Fatal error: Uncaught TypeError

朝着更安全、更健壮的代码迈出的小而重要的一步。

要求

PHP 7.1+

安装

$ composer require pwm/tc

使用

要创建一个具体的类型化集合,我们需要扩展 TypedCollection 并向它提供一个带有类型声明的函数。

例如,以下是一个整数集合的例子

class IntCollection extends TypedCollection
{
    public function __construct(...$ints)
    {
        parent::__construct(function (int $int) {
            return $int;
        }, $ints);
    }
}

要使用它

$intCollection = new IntCollection(1, 2, 3);

// iterable
foreach ($intCollection as $element) {
    assert(is_int($element) === true);
}

// countable
assert(count($intCollection) === 3);

// listable
assert($intCollection->toList() === [1, 2, 3]);

基本标量类型化集合,即 bool、callable、float、int 和 string,作为库的一部分,方便使用。

它如何工作

技巧是向 TypedCollection 提供一个函数,该函数要求其参数必须是特定类型。为此,我们只需使用 PHP 的内置函数类型声明。这既适用于内置类型,也适用于用户定义的类型(即类)。TypedCollection 还会检查所提供的类型检查函数是否真正进行类型检查,即它会在接收到未类型化的函数时抛出异常。

TypedCollection 实现了 IteratorAggregateCountable 接口,以便于使用。getIterator() 返回一个 Generator,这很好地与集合的不变语义相匹配,即您可以迭代它,访问其元素,而不必访问容器本身。

要获取底层的可变数组表示形式,请使用 toList()。这对于使用 map/filter/reduce 非常有用。

测试

$ vendor/bin/phpunit
$ composer phpcs
$ composer phpstan

变更日志

点击此处

许可

MIT