Release: 0.30.0 - Many Forms
Multimethods + walk/pprint modules + keyword interning + 15+ perf optimizations across core, data structures & REPL
🎉 Added
- Add
subset?predicate for sets:(subset? (hash-set 1 2) (hash-set 1 2 3))=>true - Add
superset?predicate for sets:(superset? (hash-set 1 2 3) (hash-set 1 2))=>true - Add
cond->macro for conditional thread-first:(cond-> 1 true inc false (* 42)) ; => 2 - Add
cond->>macro for conditional thread-last:(cond->> [1 2 3] true (map inc)) ; => [2 3 4] - Add
vecfunction to coerce collections to vectors:(vec '(1 2 3))=>[1 2 3] - Add
hash-setfunction to create sets from arguments (like Clojure'shash-set) - Add
phel\walkmodule withwalk,postwalk,prewalk,postwalk-replace,prewalk-replace,keywordize-keys, andstringify-keys - Add
phel\pprintmodule withpprintandpprint-strfor pretty-printing nested data structures with configurable width - Add
tap>,add-tap,remove-tap, andreset-taps!tophel\debugfor a global tap handler system - Add
dir,apropos, andsearch-doctophel\replfor namespace exploration and documentation search - Add
defmultianddefmethodmacros for runtime polymorphism via dispatch functions - Add
--fail-fastoption tophel testto stop on first failure or error
⚖️ Changed
- Optimize
str/blank?: single regex pass instead of character-by-character loop - Optimize
str/escape:array_map+implodeinstead of O(n²) string concatenation - Optimize
str/last-index-of: nativemb_strrposinstead of O(n²) loop - Optimize
core/reverse: nativearray_reverseinstead of element-by-elementconj - Optimize
core/interleave:reduce+conjinstead of repeatedconcat - Eliminate redundant iterations in
walk,keywordize-keys, andstringify-keys - Cache
print-valueresult inpprintto avoid redundant calls - Extract
as-patternhelper to deduplicatestr/replaceandstr/replace-first - Add identity fast-path (
===) inEqualizer::equals()to skipinstanceoffor identical values - Optimize
NodeEnvironment::hasLocal()— direct name comparison instead ofSymbol::create()+in_array - Optimize
PersistentList::get()— early bounds check, loop only to target index - Eliminate double hash lookup in
PersistentHashSet::add()/remove() - Optimize
PersistentVector::cons()— useTransientVectorinstead of full array rebuild - Deduplicate
GlobalEnvironment::getAllDefinitions()via hash keys instead ofarray_unique - Optimize
NodeEnvironment::withMergedLocals()— avoidarray_uniqueon Symbol objects - Use 2-level nested cache in
NodeEmitterFactoryto avoid string concatenation per node - Cache indentation strings in
OutputEmitter - REPL now gracefully falls back to
fgets(STDIN)when the readline extension is unavailable (Docker, CI) - Inline truthy checks at emit time — eliminates
Truthy::isTruthy()static method call overhead on every conditional - REPL and eval now use in-memory evaluation (
eval()) instead of writing temp files, significantly reducing I/O overhead and startup time assocnow accepts multiple key-value pairs in a single call (Clojure alignment):(assoc m :a 1 :b 2 :c 3)- BREAKING:
setnow coerces a collection to a set (Clojure alignment):(set [1 2 3])=>#{1 2 3} - Use
hash-setfor creating sets from arguments:(hash-set 1 2 3)=>#{1 2 3} - Keywords are now interned (flyweight pattern) — same name/namespace returns the same instance, enabling
===identity checks and reducing GC pressure
🐛 Fixed
- Restore GlobalEnvironment refers/aliases when loading from compiled code cache
- Functions used in string concatenation (e.g.
(str "Hello, " name "!")) no longer crash with a PHP error; they now render as<function:name> - Fix
zipmapcausing out-of-memory error when used with infinite lazy sequences (e.g.(zipmap keys (repeat val))) - Fix
peekcrashing when used on lazy sequences (e.g. fromfilterormap) - Fix excessive blank lines in test output between test dots and summary
- Fix REPL catch-all error handler showing raw PHP traces instead of source-mapped Phel stack traces
👥 Contributors
@Chemaclass @JesusValeraDev
Full Changelog: v0.29.0...v0.30.0
Downloads
- phel.phar (956.8 KB)