Skip to main content

Release: 0.33 - Quicksilver

Latest update

0.33.0 - Quicksilver

Released 2026-04-17 · GitHub release

New router + http-client + AI modules, UUID/ratio literals, constructor shorthand, many new predicates/seq fns, transient fast-paths, phel\strphel\string.

🎉 Added

Tooling & CLI

  • cache:warm command
  • debug:container, debug:dependencies, debug:modules, list:modules, profile:report, validate:config commands
  • build/preload.php opcache preload script
  • phel doctor Build health check and Gacela module health checks

Build & Caching

  • ScopedCache for dependency-aware cache invalidation
  • #[Cacheable] on directory lookups and namespace encoding
  • cache:clear clears Gacela class-name and merged-config caches

Testing

  • ContainerFixture trait resets Gacela container between tests
  • use-fixtures for :each / :once fixtures (#1439)

Reader & Compiler

  • (use ClassName [:as Alias] ...) top-level form
  • (ClassName. args) constructor shorthand (#1359)
  • #uuid "…" tagged literal (#1376)
  • Ratio literals N/M; 1/0INF, 0/0NaN
  • :syms map destructuring

Predicates

  • ident?, simple-ident?, simple-keyword?, simple-symbol? (#1369, #1381)
  • special-symbol? (#1384), ifn? (#1370)
  • neg-int?, pos-int?, nat-int? (#1374)
  • sequential? (#1380), seqable? (#1379)
  • any?, ratio?, instance? (#1433)

Sequences & Collections

  • nth, nthrest, nthnext (#1375)
  • fnext (#1368)
  • rseq, reversible? (#1378)
  • empty (#1365)
  • key, val (#1372)
  • (keyword ns name) arity (#1428)
  • mapcat multi-collection arity (#1428)
  • Transients callable like persistents (#1428)

PHP Interop

  • aget, aset with nested index support (#1356)
  • int-array, long-array, float-array, double-array, short-array (#1382)
  • int, long, short coercion (#1371, #1383)
  • uuid?, parse-uuid (#1377)
  • alter-var-root stub (out of scope) (#1357)
  • parse-double accepts Infinity, -Infinity, NaN (#1428)
  • alength (#1433)

Observability

  • tap>, add-tap, remove-tap; synchronous dispatch, swallows tap exceptions

Modules

  • phel\router: data-driven router on symfony/routing; routes, :route-name, per-case error handlers
  • phel\http-client: outbound HTTP over PHP streams
  • phel\ai: chat, completions, structured extraction, tool use, embeddings, semantic search
  • phel\repl AI helpers: explain, suggest, fix, review, embed-ns, search-ns

🐛 Fixed

  • CompiledCodeCache keys by source file path (cache version 1.2)
  • keyword idempotent; handles nil / symbol (#1428)
  • dissoc accepts zero keys and variadic (#1428)
  • keys / vals return nil for nil or empty (#1428)
  • make-hierarchy exposes :parents, :descendants, :ancestors (#1428)
  • first on map returns its first entry (#1428)
  • str preserves float representation; readable NaN / ±Infinity (#1428)
  • compare throws on cross-category; nil less than non-nil (#1428)
  • :keyword lookup on transient maps (#1428)
  • deftest rejects missing/non-symbol names (#1364)
  • (def name) binds nil (#1361)
  • doseq pair bindings without :in (#1362)
  • doseq iterates maps as [k v] entries (#1433)
  • is accepts scalar literals (#1433)
  • drop-last on lazy sequences and ranges (#1360)
  • (empty? (range)) terminates (#1366)
  • is handles let / when / cond (#1367)
  • defrecord / defstruct / defexception / definterface valid in statement mode (#1358)
  • defstruct / defrecord / defexception / definterface nestable in function bodies
  • phel\router error dispatch: 404/405/406
  • Namespace extractors skip build output directory

⚖️ Changed

  • Upgraded Gacela to ^1.14; #[Provides] providers with getRequired()
  • Phel::run() resolves FilesystemFacade via Gacela::getRequired()
  • composer test-quality runs validate:config
  • Dropped phpunit/php-timer; internal resource-usage formatter
  • Breaking: phel\str renamed to phel\string (#1440)
  • (load path): relative from caller file; /path classpath-absolute via phel\repl/src-dirs; ./, ../, .phel rejected
  • src/phel/core.phel split into topic files under src/phel/core/
  • Phel test files reorganized into core/
  • phel\router caches Symfony matcher/generator and precompiles middleware
  • phel test skips compile failures; --fail-fast aborts

🗑️ Removed

  • phel\debug namespace (dotrace, dbg, spy, tap, reset-trace-state!, set-trace-id-padding!)

Performance

  • Hot type predicates via php/instanceof / php/is_*: vector?, list?, set?, keyword?, symbol?, string?, boolean?, integer?, float?, number?, php-array?, indexed?, associative?, sequential?, coll?
  • every? / all? use empty? (O(1) on lazy seqs)
  • select-keys O(|ks|)
  • into transient fast-path
  • Transient accumulators in set, vec, frequencies, merge, merge-with, select-keys, rename-keys, update-keys, update-vals, invert, group-by
  • reverse, sort, sort-by, shuffle, doall, string next / rest / seq build vectors from PHP array directly
  • zipcoll delegates to zipmap
  • Removed shadowed eager interleave / interpose

👥 Contributors

@Chemaclass @JesusValeraDev

Full Changelog: v0.32.0...v0.33.0

Downloads

v0.33.0


View release on GitHub