bit-badger/inspired-by-fsharp

受 F# 对应类启发的 PHP 工具类

v2.0.0-rc1 2024-10-01 03:06 UTC

This package is not auto-updated.

Last update: 2024-10-01 03:11:10 UTC


README

此项目包含受 F# 对应类启发的 PHP 工具类。

v2 系列需要至少 PHP 8.4。此项目版本 1 中存在 PHP 8.2 - 8.3 的类似 API;具体内容请参阅其 README。

提供的内容

此处于早期阶段的库目前提供两个类,这两个类都旨在封装值并指示产生它们的操作的状态。Option<T> 代表可能或可能不具有值的变量。 Result<TOK, TError> 代表动作的结果;"ok" 和 "error" 状态都提供值。

Option<T>
替换 null 检查
Result<TOK, TError>
替换基于异常的错误处理
创建::Some(T) 用于 Some::OK(TOK) 用于 OK
::None() 用于 None::Error(TError) 用于 Error
::of($value) None 如果 null
查询->isSome: bool->isOK: bool
->isNone: bool->isError: bool
->contains(T, $strict = true): bool->contains(TOK, $strict = true): bool
->exists(callable(T): bool): bool->exists(callable(TOK): bool): bool
读取
->value: T->ok: TOK
所有在缺少值时抛出异常->error: TError
转换
->map(callable(T): TMapped): Option<TMapped>->map(callable(TOK): TMapped): Result<TMapped, TError>
所有仍然是 OptionResult->mapError(callable(TError): TMapped): Result<TOK, TMapped>
迭代->iter(callable(T): void): void->iter(callable(TOK): void): void
检查
返回原始实例
->tap(callable(Option<T>): void): Option<T>->tap(callable(Result<TOK, TError>): void): Result<TOK, TError>
继续处理->bind(callable(T): Option<TBound>): Option<TBound>->bind(callable(TOK): Result<TBoundOK, TError>): Result<TBoundOK, TError>
更改类型->toArray(): T[]->toArray(): TOK[]
->toOption(): Option<TOK>

此外,Option<T> 还提供

  • ->getOrDefault(T) 如果存在则返回 Some 值,如果 option 是 None,则返回给定的默认值。
  • ->getOrCall(callable(): mixed) 如果 option 是 None,则调用给定的函数。该函数可能返回一个值,也可能是 voidnever
  • ->getOrThrow(callable(): Exception) 如果存在则返回 Some 值,如果 option 是 None,则抛出函数返回的异常。
  • ->filter(callable(T): bool) 将 Some 值与可调用函数进行比较,如果返回 true,则保持 Some;如果返回 false,则值将变为 None。
  • ->unwrap() 对于 None 选项返回 null,对于 Some 选项返回值。

最后,我们不应该忽视这个领域的一些真正酷的先验艺术——PhpOption 项目。 Option::of 识别他们的选项并正确转换,Option<T> 实例有一个 ->toPhpOption() 方法,可以将这些转换回 PhpOption 的 Some<T>None 实例。来自同一团队还有一个 ResultType 项目,尽管这个项目的结果(目前)还没有任何转换方法。

灵感来源

F# 是一个在 .NET 下运行的 ML 风格语言。它拥有大多数函数式编程范式,但由于它运行在原本设计为面向对象运行时——并且可以使用和交互所有 .NET 库——因此它是一种实用的函数式编程方法。(许多其十年以上的特性已实现到最近的 C# 版本中。)

这个库也做了些实用的结构选择。例如,在 F# 中,可以像这样获取一个可选值...

let value =
    Option.ofObj myVar
    |> Option.map (fun it -> it.Replace("howd", "part"))
    |> Option.defaultValue "There was no string"

如果 myVarnull,则 value 将有 "没有字符串";如果 myVar 是 "howdy",则 value 将是 "party"。每个 Option 调用都将其选项作为最后一个参数,|> 是管道操作符;它将上一个值作为下一个操作的最后一个参数。这个库的先前版本有静态函数来模仿这一点,结果如下...

$value = Option::defaultValue('There was no string',
    Option::map(fn($it) => str_replace('howd', 'part', $it),
        Option::of($myVar)));

...这个顺序是从右到左(或者说是从下到上,就像它格式化那样)。通过将这些实现为实例方法,PHP 代码看起来更简洁。

$value = Option::of($myVar)
    ->map(fn($it) => str_replace('howd', 'part', $it))
    ->getOrDefault('There was no string');

如果 PHP 获得了一个管道操作符,我们将重新审视这里的大量内容(当然是以非破坏性的方式)。

想法

这个库目前具有其作者需要的特性。要提出其他建议,请通过 Fediverse 上的 @daniel@fedi.summershome.org 或 Twitter 上的 @Bit_Badger 联系 Daniel。