bluesnowman / fphp-saber
一个功能性的PHP库,它推广强类型、不可变对象和惰性求值。
This package is not auto-updated.
Last update: 2024-09-25 15:20:11 UTC
README
一个功能性的PHP库,它推广强类型、不可变对象和惰性求值。
要求
装箱
要“装箱”PHP类型原语或对象,使用类的方法 make
创建相应数据类型的实例。此方法通过将值转换为正确的数据类型来强制类型。如果值无法转换为正确的数据类型,将抛出异常。
$object = IInt32\Type::make(7);
为了更好的性能,使用 box
方法以避免其对应的 make
方法在创建实例之前可能执行的不必要的预处理。
$object = IInt32\Type::box(7);
某些数据类型使用单例方法进行初始化。例如,IUnit\Type
类的初始化如下所示
$object = IUnit\Type::instance();
同样,其他数据类型有更具体的单例方法。其中之一是 ITrit
数据类型,它有三个单例方法用于负一、零和正一。
$negative = ITrit\Type::negative();
$zero = ITrit\Type::zero();
$positive = ITrit\Type::positive();
建议尽可能使用这些工厂/单例方法来初始化数据类型,而不是使用构造函数。这既是为了传统原因,也是为了实现原因。
要“取消装箱”一个装箱对象,请在相应的类上调用unbox
方法以获取其值。
$value = $object->unbox();
流畅API
许多数据类型允许使用流畅API;因此,许多方法可以在一个语句中一起链接。通过使用PHP的神奇__call
方法,某些数据类型可以像实例方法一样访问它们各自模块的方法。(模块中的方法定义方式类似于C#中扩展方法的定义。)例如,您可以执行以下操作
$object = IInt32\Type::box(7)->increment()->decrement();
此语句在功能上等同于编写
$object = IInt32\Module::decrement(IInt32\Module::increment(IInt32\Type::box(7)));
注意:此流畅API仅适用于返回Core\Type
对象的方法。
类
Type
类为特定类型定义了一个精简的接口。
Module
类定义了一组用于处理其相应Type
类的方发。所有方法都是静态的,并且必须为其第一个参数定义相应的Type
类。
Utilities
类定义了一组与其相应Type
类相关的方发。所有方法都是静态的。
Iterator
类定义了PHP如何通过迭代器计数和遍历集合。
方法
一般来说,不是以两个下划线开头的方法将返回一个装箱对象。
$object = IInt32\Type::box(7)->increment();
此规则的例外之一是unbox
方法。
以两个下划线开头的方法将返回一个未装箱的值,这通常是一个PHP类型原始值或对象。这是通过PHP的神奇__call
方法实现的。
$value = IInt32\Type::box(7)->__increment();
这基本上在功能上等同于编写
$value = IInt32\Type::box(7)->increment()->unbox();
变量
该库为某些变量采用了以下命名约定
$c
通常表示一个携带的值。
$e
通常表示一个异常。
$i
、$j
和$k
通常表示一个索引或计数。
$n
通常表示一个数量。
$p
通常表示一个位置。
$r
通常表示一个结果。
$x
、$y
和$z
通常表示一个对象或一个值。
$xs
、$ys
和$zs
通常分别表示$x
、$y
和$z
对象/值的集合。
$xss
、$yss
和$zss
通常分别表示$xs
、$ys
和$zs
集合的集合。
$xi
、$yi
和$zi
通常分别表示$x
、$y
和$z
对象/值集合的迭代器。
$xsi
、$ysi
和$zsi
通常分别表示$xs
、$ys
和$zs
集合的迭代器。
可调用对象
$closure
函数没有预定义的签名或返回类型;但作为一个一般规则,它应该利用Core\Type对象作为参数和返回类型。
function(?Core\Type... $m) : ?Core\Type
$operator
函数用于找到对一个或多个操作数的操作符应用的结果。
function(Core\Type $c) : Core\Type
function(Core\Type $c, Core\Type $x) : Core\Type
$predicate
函数用于找到执行布尔评估的结果。
function(Core\Type $x) : IBool\Type
function(Core\Type $x, IInt32\Type $i) : IBool\Type
$procedure
函数用于执行不返回值的操作(尽管技术上PHP默认返回一个null
值)。在逻辑上使用返回语句提前终止过程的情况下,返回值必须是null
值或一个IUnit\Type
对象。
function(Core\Type $x) : ?IUnit\Type
function(Core\Type $x, IInt32\Type $i) : ?IUnit\Type
$subroutine
函数用于执行返回值的操作。
function(Core\Type $x) : Core\Type
function(Core\Type $x, IInt32\Type $i) : Core\Type
$tryblock
函数用于处理可能抛出运行时异常的代码块。
function() : Core\Type
选择
对象可以通过使用when
子句进行比较。当x
和y
匹配时(即当$x->__eq($y)
评估为true
时),when
子句会被满足。如果遇到匹配,将执行$procedure
。
$x = IInt32\Type::box(8);
$y = IInt32\Type::box(8);
Control\Type::choice($x)
->when($y, function(IInt32\Type $x) {
// passes, do something
})
->otherwise(function(IInt32\Type $x) {
// skipped
})
->end();
对象还可以通过使用unless
子句进行比较。当x
和y
都不匹配时(即当$x->__eq($y)
评估为false
时),unless
子句会被满足。如果匹配结果为假,将执行$procedure
。
$x = IInt32\Type::box(8);
$y = IInt32\Type::box(7);
Control\Type::choice($x)
->unless($y, function(IInt32\Type $x) {
// passes, do something
})
->otherwise(function(IInt32\Type $x) {
// skipped
})
->end();
序列
可以通过以下方式轻松创建包含数字序列的列表:
$object = IInt32\Module::sequence(IInt32\Type::zero(), IInt32\Type::box(5));
这表示[0..5]。它将生成[0,1,2,3,4,5]。
您还可以生成如[0,2..10]的序列,它将生成[0,2,4,6,8,10]。
$object = IInt32\Module::sequence(IInt32\Type::zero(), ITuple\Type::box2(IInt32\Type::box(2), IInt32\Type::box(10)));
类似的函数也存在于IDouble、IFloat和IInteger中。
异常
要抛出异常,请执行以下操作:
$message = 'Hi, my name is :name';
$tokens = array(':name' => 'Blue Snowman');
$code = IInt32\Type::zero();
Control\Exception\Module::raise(new Throwable\UnexpectedValue\Exception(
$message, // optional
$tokens, // optional
$code // optional
));
除了使用传统的try/catch
语句外,您还可以使用内置的try_
控制功能
$either = Control\Exception\Module::try_(function() {
// do something that might cause an exception to be thrown
});
这将把结果包裹在IEither\Type
中。按照惯例,异常将被包裹在IEither\Left\Type
中,而成功的结果将被包裹在IEither\Right\Type
中。
层次结构
以下描述了数据类型之间的关系
+ Core\Type
+ Control\Type
+ Choice\Type
+ Data\Type
+ IBool\Type
+ IChar\Type
+ ICollection\Type
+ IEither\Type
+ Left\Type
+ Right\Type
+ IMap\Type
+ IHashMap\Type
+ IOption\Type
+ Some\Type
+ None\Type
+ ISeq\Type
+ IArrayList\Type
+ ILinkedList\Type
+ IString\Type
+ ISet\Type
+ IHashSet\Type
+ ITuple\Type
+ INumber\Type
+ IFloating\Type : IFractional\Type
+ IDouble\Type : IReal\Type
+ IFloat\Type : IReal\Type
+ IIntegral\Type : IReal\Type
+ IInt32\Type
+ IInteger\Type
+ ITrit\Type
+ IRatio\Type : IFractional\Type
+ IObject\Type
+ IRegex\Type
+ IUnit\Type
+ Throwable\Runtime\Exception
+ Throwable\EmptyCollection\Exception
+ Throwable\InvalidArgument\Exception
+ Throwable\OutOfBounds\Exception
+ Throwable\Parse\Exception
+ Throwable\UnexpectedValue\Exception
+ Throwable\UnimplementedMethod\Exception
+ Throwable\Unknown\Exception
大多数数据类型都与一个模块相关联。
ICollection
类型还有一个迭代器类,以便该类可以与PHP的foreach
循环一起使用。因为这些迭代器类必须遵守PHP的Iterator
和Countable
接口,所以这些类中的方法不一定遵守此库使用的所有约定(即一些非双下划线方法将返回PHP类型原始值而不是相应的Core\Type
对象)。
单元测试
此库提供了一个方便的Makefile
,用于安装、更新和卸载Composer和PHPUnit。同样,此Makefile
也可以用来运行此库中包含的任何单元测试。
要运行此Makefile
,请导航到硬盘中它所在的位置,然后输入以下命令中的任何一个:
安装Composer和PHPUnit
make install
更新Composer和PHPUnit
make update
卸载Composer和PHPUnit
make uninstall
运行所有单元测试
make unit-test
仅运行特定组的单元测试,例如
make unit-test GROUP=TypeTest
有关其他命令的更多信息,请参阅Makefile
中的文档。
拉取请求
帮助改进此库。如果您有错误修复、建议或改进,请提交包含任何适用测试用例的拉取请求。
许可证
版权所有 2014-2016 Blue Snowman
根据Apache许可证第2版(“许可证”)授权;除非您遵守许可证,否则不得使用此文件。您可以在以下位置获取许可证副本:
https://apache.ac.cn/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则根据许可证分发的软件按“原样”分发,不提供任何明示或暗示的保证或条件。有关许可证的具体语言规定权限和限制,请参阅许可证。