Object-functional language extension to Java 8+ providing persistent collections, functional abstractions, and monadic control types.
npx @tessl/cli install tessl/maven-io-vavr--vavr@0.10.0Vavr is an object-functional language extension to Java 8+ that brings functional programming concepts to Java development. It provides persistent collections, functional abstractions for error handling, concurrent programming utilities, and pattern matching capabilities. Vavr enables developers to write more concise, safe, and functional code while maintaining full Java interoperability.
implementation 'io.vavr:vavr:0.10.6' (Gradle) or <dependency><groupId>io.vavr</groupId><artifactId>vavr</artifactId><version>0.10.6</version></dependency> (Maven)import io.vavr.*;
import io.vavr.collection.*;
import io.vavr.control.*;
import io.vavr.concurrent.*;
import static io.vavr.API.*; // Pattern matching and utilities
import static io.vavr.Patterns.*; // Pattern matching patternsCommon specific imports:
import io.vavr.collection.List;
import io.vavr.collection.Map;
import io.vavr.collection.Stream;
import io.vavr.control.Option;
import io.vavr.control.Either;
import io.vavr.control.Try;
import io.vavr.control.Validation;
import io.vavr.concurrent.Future;
import io.vavr.concurrent.Promise;import io.vavr.collection.List;
import io.vavr.control.Option;
import io.vavr.control.Try;
import static io.vavr.API.*;
import static io.vavr.Patterns.*;
// Immutable collections
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> doubled = numbers.map(x -> x * 2);
List<Integer> evens = numbers.filter(x -> x % 2 == 0);
// Option instead of null
Option<String> maybeValue = Option.of("Hello");
String result = maybeValue.map(String::toUpperCase).getOrElse("DEFAULT");
// Exception handling with Try
Try<Integer> computation = Try.of(() -> Integer.parseInt("123"));
String outcome = computation
.map(x -> "Success: " + x)
.getOrElse("Failed to parse");
// Pattern matching
String description = Match(numbers.size()).of(
Case($(0), "empty"),
Case($(1), "single"),
Case($(), "multiple")
);Vavr is built around several key architectural principles:
Essential building blocks including value types, lazy evaluation, tuples, and functional interfaces.
interface Value<T> {
// Core value interface with conversion methods
Option<T> toOption();
Try<T> toTry();
<U> List<U> toList();
}
class Lazy<T> implements Value<T> {
static <T> Lazy<T> of(Supplier<? extends T> supplier);
T get();
boolean isEvaluated();
}
interface Tuple {
static Tuple0 empty();
static <T1> Tuple1<T1> of(T1 t1);
static <T1, T2> Tuple2<T1, T2> of(T1 t1, T2 t2);
// ... up to Tuple8
}Comprehensive collection library with persistent data structures, including lists, sets, maps, and specialized collections.
interface List<T> extends LinearSeq<T> {
static <T> List<T> of(T... elements);
static <T> List<T> empty();
T head();
List<T> tail();
List<T> prepend(T element);
<U> List<U> map(Function<? super T, ? extends U> mapper);
List<T> filter(Predicate<? super T> predicate);
}
interface Map<K, V> extends Traversable<Tuple2<K, V>> {
static <K, V> Map<K, V> of(K k1, V v1);
static <K, V> Map<K, V> empty();
Option<V> get(K key);
Map<K, V> put(K key, V value);
Map<K, V> remove(K key);
}Monadic control structures for error handling, optional values, and validation with functional composition.
interface Option<T> extends Value<T> {
static <T> Option<T> of(T value);
static <T> Option<T> some(T value);
static <T> Option<T> none();
boolean isDefined();
T get();
<U> Option<U> map(Function<? super T, ? extends U> mapper);
<U> Option<U> flatMap(Function<? super T, ? extends Option<? extends U>> mapper);
}
interface Either<L, R> extends Value<R> {
static <L, R> Either<L, R> left(L left);
static <L, R> Either<L, R> right(R right);
boolean isLeft();
boolean isRight();
<U> Either<L, U> map(Function<? super R, ? extends U> mapper);
}
interface Try<T> extends Value<T> {
static <T> Try<T> of(CheckedFunction0<? extends T> supplier);
boolean isSuccess();
boolean isFailure();
<U> Try<U> map(Function<? super T, ? extends U> mapper);
Try<T> recover(Function<? super Throwable, ? extends T> recovery);
}Asynchronous programming utilities with Futures, Promises, and functional composition for concurrent operations.
interface Future<T> extends Value<T> {
static <T> Future<T> of(Executor executor, CheckedFunction0<? extends T> computation);
static <T> Future<T> successful(T value);
boolean isCompleted();
<U> Future<U> map(Function<? super T, ? extends U> mapper);
<U> Future<U> flatMap(Function<? super T, ? extends Future<? extends U>> mapper);
Future<T> recover(Function<? super Throwable, ? extends T> recovery);
}
interface Promise<T> {
static <T> Promise<T> make();
boolean trySuccess(T value);
boolean tryFailure(Throwable exception);
Future<T> future();
}Extended function interfaces with composition, memoization, and exception handling capabilities.
@FunctionalInterface
interface Function1<T1, R> extends java.util.function.Function<T1, R> {
static <T1, R> Function1<T1, R> of(Function1<T1, R> function);
default Function1<T1, R> memoized();
default <V> Function1<T1, V> andThen(Function<? super R, ? extends V> after);
}
@FunctionalInterface
interface CheckedFunction1<T1, R> {
R apply(T1 t1) throws Throwable;
default Function1<T1, Try<R>> unchecked();
}Structural pattern matching for control flow and data destructuring with compile-time safety.
// Core pattern matching API
static <T> Match.Case<T, ?> Case(Pattern<T> pattern, Object value);
static <T> Match.Case<T, ?> Case(Pattern<T> pattern, Supplier<Object> supplier);
static <T> Match.Case<T, ?> Case(Pattern<T> pattern, Function<T, Object> function);
// Pattern matching entry point
static <T> Match<T> Match(T value);
// Pattern creators
static <T> Pattern<T> $(T prototype); // Exact match
static <T> Pattern<T> $(); // Wildcard match
static <T> Pattern<T> $(Predicate<T> predicate); // Conditional match
// Object patterns for data types
static <T> Pattern<Option<T>> Some(Pattern<T> pattern);
static Pattern<Option<?>> None();
static <L, R> Pattern<Either<L, R>> Left(Pattern<L> pattern);
static <L, R> Pattern<Either<L, R>> Right(Pattern<R> pattern);
static <T> Pattern<Try<T>> Success(Pattern<T> pattern);
static <T> Pattern<Try<T>> Failure(Pattern<Throwable> pattern);Pattern matching enables expressive and type-safe control flow:
// Matching on data types
String result = Match(option).of(
Case($Some($()), value -> "Found: " + value),
Case($None(), "Not found")
);
// Matching with guards
String category = Match(number).of(
Case($(n -> n < 0), "negative"),
Case($(0), "zero"),
Case($(n -> n > 0), "positive")
);Vavr provides extensive interoperability with Java standard library types:
// Converting from Java to Vavr
List<String> vavrList = List.ofAll(Arrays.asList("a", "b", "c"));
Option<String> vavrOption = Option.of(javaOptional.orElse(null));
// Converting from Vavr to Java
java.util.List<String> javaList = vavrList.asJava();
java.util.Optional<String> javaOptional = vavrOption.toJavaOptional();
java.util.stream.Stream<String> javaStream = vavrList.toJavaStream();