Phel v0.36.0:将数值塔和一等公民变量引入 PHP
Phel 是一种受 Clojure 启发的 Lisp,编译为 PHP,已发布 0.36.0 版本。此更新在语言的精度和灵活性上实现了重大飞跃,引入了强大的数值塔和一等公民 Var 句柄。对于希望将 Lisp 的表达能力与 PHP 生态的普遍性相结合的开发者而言,这些改动提供了高精度算术和高级元编程的关键工具。
数值塔:精度与任意尺度
v0.36.0 中最重要的新增功能之一是实现了“数值塔”,使 Phel 能够处理远超标准 PHP 浮点数和整数精度的数字。
有理数与大整数
- 精确有理数: Phel 现在支持比值字面量(例如
1/2、-3/4),直接解析为Rational类型。这消除了分数在浮点除法中固有的四舍五入误差。 - 大整数支持: 语言现在加入了
BigInteger用于任意精度整数。值得注意的是,PHP 整数在算术运算(+、-、*、**)溢出时会自动提升为BigInteger,确保计算不会悄悄回绕或失去精度。 - 大十进制(BigDecimal): 为了进行固定精度的十进制算术,现已提供
BigDecimal,使用M后缀字面量(例如1.5M)。
算术行为的变化
为了支持该塔,多个核心行为已发生变化。最显著的是,(/ int int) 在结果不是整数时会返回 Rational,而不再默认返回浮点数。需要浮点除法的开发者应显式使用 (double ...),或确保其中一个操作数为浮点数(例如 (/ 1.0 2))。
一等公民变量与动态绑定
0.36.0 版本引入了一等公民 Var 句柄,超越了简单的符号解析,使开发者能够将变量本身作为对象进行操作。
新的 Var 能力
- Var 句柄: 新的
(var sym)特殊形式和#'sym读取宏允许创建和操作Var句柄。 - 动态重新绑定: 使用
with-redefs和with-bindings,开发者现在可以从映射中重新绑定动态变量,系统会确保即使出现异常也能恢复原始值。 - 可观察性:
PhelVarStateRegistry现在支持“监视”,开发者可以使用add-watch和remove-watch在通过alter-var-root更改Var时触发相应操作。
扩展的类型系统与集合
除了数字和变量,Phel 还扩展了原生值类型集合,以更好地满足现代应用需求:
- UUID: 通过
#uuid "..."、random-uuid和parse-uuid原生支持 UUID。 - 持久队列: 新的
PersistentQueue提供 FIFO 结构,对push、peek、pop操作具有摊销 O(1) 性能。 - PHP 集成:
PhpClass值类型现在包装规范化的 PHP 类/接口全限定名(FQN),简化 Lisp 与 PHP 之间的桥接。 - MapEntry:
MapEntry类型现在在值上等同于 2 元素向量,提升哈希映射迭代的易用性。
性能与工具改进
此版本的效率提升主要聚焦于启动过程中的开发者体验(DX):
- 更快的启动时间: REPL 和测试运行器现在在扫描时会剔除常见的大型目录,如
vendor/、.git/和node_modules/,并对目录扫描进行进程级缓存。 - 优化的测试:
phel test命令现在加入了强大的新标志:--list用于发现测试而不执行,--last-failed用于回归迭代,--slowest=N用于定位测试套件中的性能瓶颈。 - 命名空间标准化: 核心库已将
(use ...)语句的类全限定名改为点分隔形式,提供更一致的语法。
破坏性变更概述
升级到 v0.36.0 的用户应注意以下几项破坏性变更:
- 除法: 当结果为非整数时,
(/ int int)现在返回Rational而非float。 - UUID:
uuid?现在严格接受Phel\Lang\Uuid对象,而不再接受原始字符串。 - 绑定:
binding函数现在对非动态变量抛出InvalidArgumentException;应改用with-redefs。