Releases: guizmaii-opensource/zazr
Releases · guizmaii-opensource/zazr
Release list
Zazr 0.1.0
Zazr 0.1.0
Website: zazr.dev
The first release.
Zazr is a fork of the latest Vavr, its main branch as of September 2026 (later than the 1.0.1 release), redesigned for Java 25: its collections come from the Scala 2.13 collections library (which Scala 3 uses unchanged), and its names and most control types from ZIO and zio-prelude (Using is a port of Scala's scala.util.Using). It is not a drop-in replacement: the package is dev.zazr, the Maven group is dev.zazr, and much of the API changed on purpose. The entries below compare Zazr 0.1.0 with Vavr.
- Artifacts:
dev.zazr:zazr-coreanddev.zazr:zazr-test. - JDK 25 or later. No runtime dependencies.
Useful links
- Getting started: add the dependency and write your first lines.
- New to functional programming?: the ideas behind the library, without jargon.
- Control types:
Option,Either,Try,Validation,Using,Lazy. - Collections, with the cost of every operation.
- Java interop:
asJava()views, streams and collectors. - Testing: property-based tests with
zazr-test. - Compared to Vavr: everything renamed, removed or changed, for moving code over.
- Zazr in your AI assistant: the Agent Skill.
Added
Control types
Validationkeeps every error: its error side is aNonEmptyVector<E>, andzipaccumulates errors without changing the type.collectAll,forEachandpartitionvalidate a whole collection;fromPredicatebuilds a check whose error can name the rejected value;flatMapEitherchains a step that returns anEither.zip,zipWith,zipLeftandzipRightonOption,Either,Try,ValidationandLazy.- Static
zipandzipWithtaking 2 to 8 values at once, such asValidation.zipWith(name, age, email, User::new), with no nested tuples. - Static
flattenon every control type, such asOption.flatten(Option<Option<A>>). Try.fromCompletableFutureandTry.toCompletableFuture.
Using
Using.of(resource, block)runs a block with a resource and returns aTry.Using.manager(block)handles any number of resources, known only at run time. Resources are released in reverse order, each once, even when an acquisition fails.- A value that is not an
AutoCloseable, such as a held lock, is registered with its own release action. - An error thrown while releasing is never lost: the more severe one surfaces and the other is attached to it as suppressed.
NonEmptyVector
- A new collection that always holds at least one element, with the whole
VectorAPI. head,last,max,minandreducecannot fail, since there is no empty case.- Operations that keep at least one element (
map,append,sorted...) return aNonEmptyVector. Operations that can remove every element (filter,tail,take...) return aVector. Vector.toNonEmptyVector()andNonEmptyVector.fromIterable(...)narrow to it, returning anOption.NonEmptySet,NonEmptySortedSet,NonEmptyMapandNonEmptySortedMap, on the same model, overHashSet,TreeSet,HashMapandTreeMap.groupByandtoMapon a non-empty collection return aNonEmptyMap.
Collections
partitionMapon the sequences and the hash sets: one pass, with a function that returns anEither.duplicatesandduplicatesByon the sequences: the elements that occur more than once.- Static
flattenon every collection except the maps. putAllon the maps: many entries at once, the argument winning on a shared key, as Scala's++does.mergekeeps the receiver's entries.- Typed
sumInt,sumLong,sumDouble,productInt,productLong,productDoubleandaverageon the sequences and sets, each taking the function that reads the number from an element. Theintandlongforms give the exact result or throwArithmeticExceptionwhen it doesn't fit, whatever the iteration order. - Positional operations (
head,last,take,drop,sliding...) on the ordered sets and maps:LinkedHashSetandLinkedHashMapin insertion order,TreeSetandTreeMapin sorted order. - Every operation whose cost depends on the size documents it in its javadoc. The complexity page lists them all.
Builders
Vector.Builder,List.Builder,HashMap.Builder,HashSet.Builder,LinkedHashMap.Builder,LinkedHashSet.Builder,TreeMap.BuilderandTreeSet.Builder: fill a collection in place, then get it once withresult(). Building in a loop no longer copies the collection at each step.ofAll,ofEntriesandcollector()of these types use their builder.
Java interop
asJava()on every collection: a read-onlyjava.utilview made in constant time, with no copy. The sequences give ajava.util.List,HashSetaSet,LinkedHashSetaSequencedSetandTreeSetaNavigableSet.asJavaMap()on the maps: ajava.util.Map, aSequencedMapforLinkedHashMap, aNavigableMapforTreeMap.ofAllgiven such a view returns the original collection without copying.
zazr-test
- A new artifact for property-based testing, after zio-test, that works inside any test framework, such as JUnit. The module is
dev.zazr.test, and it depends on no test framework. - One
Gentype with growing sizes, finite generators and a seeded, replayable run; no shrinking.Check.check(gen, ...)fails the test itself with the counterexample, the sample number and the seed;Check.evaluatereturns aCheckResultyou can pattern match on (Satisfied,Falsified,Erroneous). Assertion: composable checks (equalTo,isGreaterThan,hasSize,contains,isSome,isRight,isValid,throwsA...) that explain why they failed, used asassertThat(value, assertions...)orCheck.check(gen, assertions...). AssertJ or JUnit assertions work as bodies too.- Generators for every Zazr type, including unusual shapes: vectors built by dropping a prefix, sets and maps that went through removals, lazy lists with an unevaluated tail.
- Law suites that check the equality,
map,flatMap,zip, builder and collection rules of your own types, and name the law that failed.
Documentation
- The website zazr.dev: getting started, a page per control type and per collection, the complexity page,
zip, builders, Java interop, testing, a page for readers new to functional programming, and the comparison with Vavr. - An Agent Skill for coding assistants, in the open Agent Skills format: copy
skills/zazrinto your assistant and it writes idiomatic Zazr code. The AI assistant page says how to install it. Its examples are compiled and run by the build, like the website's.
Changed
Whole library
- Java 25 is the minimum. The module is
dev.zazrand exportsdev.zazr,dev.zazr.collectionanddev.zazr.control. - No
nullinside.Some,Right,Success,Validand every collection reject it with aNullPointerException.Option.some(null)throws; useOption.ofNullable. A function that returnsnullwhere a value is needed (aflatMapmapper, a classifier, a supplier) fails at once, with a message naming the method. - Operations use the JDK's functional interfaces:
Supplier,Function,BiFunction,Callable.Function3toFunction8andCheckedFunction1toCheckedFunction8remain, since the JDK has nothing at those arities or with checked exceptions. - Names say what an operation does, following ZIO:
apbecomeszip/zipWith,sequencebecomescollectAll,traversebecomes the staticforEach,bimapbecomesmapBoth,peekbecomestap, and on the sequences and setsmapTobecomesas. The Compared to Vavr page has the full table. - The javadoc is written in Markdown.
Control types
Option,Either,TryandValidationare sealed interfaces of records (Some/None,Left/Right,Success/Failure,Valid/Invalid), so pattern matching on them is checked by the compiler.- They are no longer
Iterable, and they no longer share a common supertype with the collections. Each has a short set of conversions:toOption(),toEither(),toTry(...),toValidation(...),toVector()... Try:recoverandrecoverWithbecomecatchAll,catchSome,catchAllWithandcatchSomeWith;mapFailurebecomesmapError;andFinallybecomesensuring;onFailurebecomestapError.Try.oftakes aCallable.- Two
Try.Failures are equal when they hold the sameThrowableinstance, not when their stack traces match. Either:swapbecomesflip,peekLeftbecomestapLeft, andEither.collectAllstops at the firstLeft. To collect every error, useValidation.Validation.condandEither.condbecomefromPredicate, whose error function receives the rejected value.
Collections
- Each collection is a concrete type that declares its own API and returns its own type:
Vector.mapreturns aVector,List.filteraList. The sequences share onlyTraversable, which holds what every collection does at the same cost (size,contains,exists,foldLeft,mkString,stream()...). The sets also shareSet(andSortedSetforTreeSet), the mapsMap(andSortedMapforTreeMap). Listis a sealed interface of two records,ConsandNil, so you can pattern match on its head and tail.
...