Phel v0.36.0: 数値タワーとファーストクラス変数を PHP に導入

Phel, a Clojure-flavored Lisp that compiles to PHP, has released version 0.36.0. This update represents a major leap in the language's precision and flexibility, introducing a robust numeric tower and first-class Var handles. For developers looking to combine the expressive power of Lisp with the ubiquity of the PHP ecosystem, these changes provide critical tools for high-precision arithmetic and advanced metaprogramming.

Phel は Clojure 風の Lisp で PHP にコンパイルされるもので、バージョン 0.36.0 をリリースしました。このアップデートは、言語の精度と柔軟性における大きな飛躍を示し、堅牢な数値タワーとファーストクラス Var ハンドルを導入します。Lisp の表現力と PHP エコシステムの普遍性を組み合わせたい開発者にとって、これらの変更は高精度演算と高度なメタプログラミングのための重要なツールを提供します。

数値タワー: 精度と任意スケール

One of the most significant additions in v0.36.0 is the implementation of a "numeric tower," allowing Phel to handle numbers with far greater precision than standard PHP floats and integers.

v0.36.0 の最も重要な追加点の一つは「数値タワー」の実装で、Phel が標準的な PHP の float や integer よりはるかに高い精度で数値を扱えるようになりました。

有理数とビッグインテジャー

  • Exact Rationals: Phel は比リテラル(例: 1/2-3/4)をサポートし、直接 Rational 型にパースします。これにより、分数の浮動小数点除算に固有の丸め誤差がなくなります。
  • BigInteger Support: 言語は任意精度整数のために BigInteger を導入しました。特に、算術演算 (+, -, *, **) 中にオーバーフローが発生すると、PHP の整数は自動的に BigInteger に昇格し、計算が黙ってラップしたり精度を失ったりしないようにします。
  • BigDecimal: 固定精度の十進演算のために BigDecimal が利用可能になり、M サフィックスリテラル(例: 1.5M)で表現します。

算術における振る舞いの変更

To support this tower, several core behaviors have changed. Most notably, (/ int int) now returns a Rational if the result is not an integer, rather than defaulting to a float. Developers requiring float division should explicitly use (double ...) or ensure one operand is a float (e.g., (/ 1.0 2).

このタワーをサポートするために、いくつかのコアな振る舞いが変更されました。特に、(/ int int) は結果が整数でない場合に Rational を返すようになり、従来のようにデフォルトで float になることはありません。float 除算が必要な開発者は、明示的に (double ...) を使用するか、オペランドの一方を float にする(例: (/ 1.0 2))必要があります。

ファーストクラス Var と動的バインディング

Version 0.36.0 introduces first-class Var handles, moving beyond simple symbol resolution to allow developers to manipulate the variables themselves as objects.

バージョン 0.36.0 はファーストクラス Var ハンドルを導入し、単なるシンボル解決を超えて、開発者が変数自体をオブジェクトとして操作できるようにします。

新しい Var の機能

  • Var Handles: 新しい特殊形式 (var sym) とリーダーマクロ #'sym により、Var ハンドルの作成と操作が可能になります。
  • Dynamic Rebinding: with-redefswith-bindings を使用すると、開発者はマップから動的 Var を再バインドでき、例外が発生した場合でも元の値が復元されることが保証されます。
  • Observability: PhelVarStateRegistry は「ウォッチ」をサポートし、add-watchremove-watch を使用して、alter-var-root によって Var が変更されたときにアクションをトリガーできます。

拡張された型システムとコレクション

Beyond numbers and vars, Phel has expanded its set of native value types to better integrate with modern application requirements:

数値と Var を超えて、Phel はネイティブ値型のセットを拡張し、現代のアプリケーション要件により適合させました:

  • UUIDs: #uuid "..."random-uuidparse-uuid による UUID のネイティブサポート。
  • Persistent Queues: 新しい PersistentQueue は FIFO 構造を提供し、pushpeekpop 操作が償却 O(1) の性能で実行できます。
  • PHP Integration: PhpClass 値型は正規化された PHP クラス/インターフェースの完全修飾名 (FQN) をラップし、Lisp と PHP の橋渡しを簡素化します。
  • MapEntry: MapEntry 型は 2 要素ベクタと値で等価となり、ハッシュマップのイテレーションの使い勝手が向上しました。

パフォーマンスとツールの改善

Efficiency gains in this release focus heavily on the developer experience (DX) during the boot process:

このリリースの効率向上は、ブートプロセス中の開発者体験 (DX) に大きく焦点を当てています:

  • Faster Boot Times: REPL とテストランナーは、スキャン時に vendor/.git/node_modules/ などの一般的に重いディレクトリを除外し、ディレクトリスキャンはプロセスごとにメモ化されます。
  • Optimized Testing: phel test コマンドは新しい強力なフラグを備えました: --list はテストを実行せずに検出し、--last-failed は失敗したテストの再実行を支援し、--slowest=N はテストスイートのパフォーマンスボトルネックを特定します。
  • Namespace Standardization: コアライブラリは (use ...) 文でドット区切りのクラス FQN に移行し、エコシステム全体でより一貫した構文を提供します。

破壊的変更の概要

Users upgrading to v0.36.0 should be aware of a few breaking shifts:

v0.36.0 にアップグレードするユーザーは、いくつかの破壊的な変更に注意する必要があります:

  1. Division: 結果が整数でない場合、(/ int int)float の代わりに Rational を返します。
  2. UUIDs: uuid? は生の文字列ではなく、Phel\Lang\Uuid オブジェクトのみを受け付けるようになりました。
  3. Binding: binding 関数は非動的 Var に対して InvalidArgumentException をスローするようになり、代わりに with-redefs を使用すべきです。

Sources