原文
First-class Vars + Ratios/BigInteger/BigDecimal numeric tower + Uuid/PhpClass/MapEntry/Queue types + faster test/REPL scans.
🎉 Added
Compiler
(var sym)special form for first-classVarhandles (#1717)#'symreader macro for(var sym)(#1717)- Ratio literals
1/2,-3/4parse toRational(#1825)
Lang
Phel\Lang\Uuidvalue type;#uuid "...",random-uuid,parse-uuidreturnUuidPhel\Lang\PhpClassvalue type wrapping a normalised PHP class/interface FQNPhel\Lang\Collections\Map\MapEntryvalue type, equal by value to a 2-element vectorPhel\Lang\Collections\Queue\PersistentQueuepersistent FIFO with amortised O(1)push/peek/pop(#1869)Phel\Lang\BigDecimalvalue type;M-suffix literals1.5M,1.5e3MPhel\Lang\BigIntegerandPhel\Lang\Rationalvalue types (#1825)Phel\Lang\NumericOperationsruntime dispatch forRational,BigInteger, native numbers (#1825)PhelVaris callable, exposesaddWatch/removeWatch/alterMeta/resetMeta/isDynamicPhelVarStateRegistrysingleton for watches, meta overrides, dynamic-flag cache
Core
Vartype withderef,meta,alter-var-root(#1717)find-var,var-get,var?,bound?,thread-bound?,var-set(#1717)with-redefsfor any var, restores on exceptionwith-bindingsrebinds dynamic vars from aVar -> valuemapadd-watch/remove-watchtargetVar, fire onalter-var-rootalter-meta!/reset-meta!survivedefredefinitionssymbolaccepts aVar(#1821);special-symbol?recognizesvar(#1822)ratio?,bigint?,numerator,denominator,rationalize(#1825)quot,rem,mod;%aliasesrem(#1831)floor,ceil,round,sqrt(#1831)+',-',*',inc',dec'auto-promoting variants (#1831)bigint,bigintegerconstructors (#1831)map-entryconstructor;map-entry?predicate (MapEntryor 2-element vector);key/valwork on eitherclass,class?,class-nameforPhpClassbigdecconstructor;bigdec?/decimal?predicates(queue & xs)constructor andqueue?predicate (#1869)typereturns:uuid,:php/class,:map-entry,:queue,:bigdec,:atom,:var,:ratio,:bigint
Testing
phel test --listprints discovered tests after applying filters/selectors and skips executionphel test --last-failedre-runs only tests that failed on the previous run; failures persist to.phel/last-failed.txtphel test --slowest=Nprints the N slowest tests after the summary
Documentation
docs/numeric-tower.mdcoversint/BigInteger/Rational/float(#1832)
⚖️ Changed
Compiler
- Zero-denominator ratio literals raise
ZeroDenominatorRatioParserExceptionat parse time (#1825)
Lang
(first m)and(next m)yieldMapEntryinstances;MapEntryequals a 2-vector both ways (#1868)assocandconjonMapEntryreturn aPersistentVector;(nth entry idx)and(count entry)work directly (#1871)BigDecimal::__toStringreturns the canonical decimal form without theMsuffix;pr/prnkeep the suffix (#1877)printerrenders rationals asn/d(#1825)
Stdlib
- Top-level
(use ...)insrc/phel/core/*uses dot-separated class FQNs with-mocks/with-mock-wrapperexpand towith-redefs*ns*bootstrap is"phel.core"(dot form)- Arithmetic, comparisons, predicates dispatch on
Rational/BigInteger(#1825)
🐛 Fixed
Compiler
- Symbol/keyword names ending in
'(inc',dec',+',-',*') resolve cross-namespace - Oversize decimal int literals lex as
float(#1837) clojure.lang.XFQNs resolve to\Phel\Lang\X(BigInttoBigInteger,RatiotoRational) (#1840)LiteralEmitter::emitFloatskips.0when the rendered float carries.or an exponent (#1846)N-suffix int literals beyondPHP_INT_MAXparse asBigInteger(#1850)LiteralEmitter::emitFloatemitsNAN/INF/-INFas constants on PHP 8.5 (#1898)VarEmitterprefixes\Phel\Lang\Registrywith leading backslash so(var sym)resolves outsidephel\\namespaces
Core
+,-,*,/mixing##Inf/##NaNwithBigDecimalfall back to float arithmetic (#1887)vector?returnstrueforMapEntryproduced by hash map iteration (#1889)BigDecimalwith a float in+,-,*,/,quot,rem,mod,comparereturns a float (#1891)rationalizeuses the shortest round-trip decimal (#1832)float/doubleacceptRationalandBigInteger(#1836)integer?acceptsBigInteger;int?stays PHP-int only (#1837)int/long/short/byteacceptRational,BigInteger,BigDecimal(#1842, #1867)int/long/short/byteon float route throughBigInteger::fromFloat; out-of-range raisesOverflowException,NaN/InfraiseInvalidArgumentException(#1846)quotreturnsfloatwhen any operand is float (#1844)abs(PHP_INT_MIN)returnsBigInteger 9223372036854775808(#1844)bigintaccepts floats, truncates toward zero, rejectsNaN/Inf; uses shortest round-trip decimal (#1845, #1852)pos-int?/neg-int?/nat-int?acceptBigIntegersymbolrejects non-name input withInvalidArgumentException;(symbol nil name)returns unqualified symbol (#1859)zero?/pos?/neg?,</<=/>/>=,==,number?routeBigDecimalthrough the numeric tower (#1867)bigdecacceptsRational; non-terminating expansions raiseArithmeticError(#1873)+,-,*,/,abs,quot,rem,mod,rationalizeacceptBigDecimal;/raisesArithmeticErroron non-terminating expansions (#1875)
Lang
=betweenintandBigIntegeris symmetric (#1830)+,-,*,**on PHP ints auto-promote toBigIntegeron overflow (#1830)(/ 1.0 0.0)returns##Inf;(/ -1.0 0.0)returns##-Inf;(/ 0.0 0.0)returns##NaN(#1830)
Testing
--filterand:filtersdrop non-matching tests at discovery instead of markingS(#1888)
Performance
- REPL boot prunes
vendor/,.git/,node_modules/at scan descent; directory scans memoised per process (#1885) bin/phel test --ns 'pat.**'preloads only matching namespaces and their dependency closurebin/phel testskips re-registering dependency-graph entries on cache hits and re-restoring a namespace's environment after the first fileNamespaceCollectorcollapses three overlapping directory scans into one (#1901)
Breaking
Core
bindingthrowsInvalidArgumentExceptionfor non-^:dynamicvars; usewith-redefs(/ int int)with non-integer result returnsRational; use(/ 1.0 2)or(double ...)for float division (#1825)uuid?accepts onlyPhel\Lang\Uuid; wrap strings withparse-uuidor#uuid "...";random-uuid/parse-uuidands/coerce :uuidreturnUuid;s/validate :uuidstill accepts canonical strings
🗑️ Removed
Core
Documentation
- README updated for dot-separated namespace syntax
👥 Contributors
@Chemaclass @Lacsw @jasalt @JesusValeraDev @SAY-5
Full Changelog: v0.35.0...v0.36.0