What Zazr is¶
Zazr gives Java immutable collections and the types that make functional code pleasant: Option, Either,
Try, Validation and Lazy. It is built for Java 25: sealed interfaces, records and pattern matching are at the core
of its API. Its collections come from the Scala 2.13 collections library, which Scala 3 uses
unchanged; its names and most of its control types come from ZIO and zio-prelude, and Using from Scala's
scala.util.Using.
What it brings¶
-
Collections that state their cost
Every operation whose cost depends on the size documents it, and one page lists them all. You choose a collection for what you do with it.
-
Persistent collections you can build fast
A builder fills a collection in place and hands it over once, so building one in a loop copies nothing.
-
Errors you do not lose
Validationcollects every error instead of stopping at the first, in a list that is never empty. -
Combine up to eight values in one call
zipWithtakes all of them and a function of their values, with no nested tuples to unpack. -
Collections that cannot be empty
On a
NonEmptyVector,head,maxandreducecannot fail, and the return types tell you when that guarantee is lost. -
Pattern matching on results
Option,Either,TryandValidationare sealed interfaces of records, so pattern matching on them is checked by the compiler. -
No
nullinside
Values and collections reject it, and absence is an
Option. -
Java interop without copies
asJava()gives a read-onlyjava.utilview in constant time, and the way back does not copy either. -
Names that say what happens
zip,collectAll,catchAll,mapBoth: the vocabulary of ZIO, with no theory to learn first.
Zazr is AI ready¶
Teach your coding assistant Zazr. The Zazr Agent Skill gives it the rules, the names and the sharp edges, so it writes idiomatic Zazr code.
A short tour¶
// Validation keeps every error, not the first one
var user = Validation.zipWith(name(""), age(-1), email("jules"), User::new); // Validation<String, User>
var message = switch (user) {
case Valid(var u) -> "hello " + u.name();
case Invalid(var errors) -> errors.mkString(", ");
};
// "name is blank, age is negative, email has no @"
// zip at any arity up to 8, no Tuple2<Tuple2<A, B>, C>
var sum = Option.zipWith(Option.some(1), Option.some(2), Option.some(3),
(a, b, c) -> a + b + c); // Option<Integer>
// total operations on a collection that cannot be empty
var scores = NonEmptyVector.of(7, 3, 9);
var best = scores.max(Integer::compare); // Integer
// a builder instead of repeated append
var builder = Vector.<Integer>newBuilder();
for (int i = 0; i < 1_000; i++) {
builder.add(i);
}
var numbers = builder.result();
name, age and email each return a Validation<String, ...>; Validation shows them.
Where the ideas come from¶
-
Scala 2.13+ collections
The Scala 2.13 collections library, which Scala 3 uses unchanged: the
Vectorand its builder, the hash tries ofHashSetandHashMap, the fully lazyLazyList, and a table of what each operation costs. Sealed interfaces, records andswitchbring Scala's pattern matching to Java. -
ZIO
The operation names (
zipWith,collectAll,forEach,tap,catchAll,mapBoth), one name per operation, and one default sequence with documented costs, asChunkis in ZIO. -
zio-prelude
Validationwith its errors in a non-empty collection,zipto combine independent values, and a non-empty collection whose return types say when it may become empty.
Zazr started as a fork of Vavr. Coming from Vavr? This page lists what changed.
Install¶
JDK 25 or later, no runtime dependencies. Zazr is on Maven Central.
dev.zazr:zazr-test adds property-based testing; see Testing with zazr-test.