File: README.md
Vavr
____ ______________ ________________________ __________
\ \/ / \ \/ / __/ / \ \/ / \
\______/___/\___\______/___/_____/___/\___\______/___/\___\Vavr is an object-functional extension for Java that makes defensive programming easy by leveraging immutability and functional control structures
Vavr seamlessly combines object-oriented programming with the elegance and robustness of functional programming.
It provides:
- persistent collections
- functional abstractions for error handling, concurrent programming
- pattern matching
- ...and more
Since Vavr has no dependencies beyond the JVM, you can easily add it as a standalone .jar to your classpath.
Led and maintained by @pivovarit
Stargazers over time
Maven Dependency
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>1.0.0</version>
</dependency>Gradle Dependency
implementation 'io.vavr:vavr:1.0.0'Using Vavr
See User Guide and/or Javadoc.
Useful Maven Goals
- Executing tests:
mvn clean test - Executing doclint:
mvn javadoc:javadoc - Executing code coverage report:
mvn -P ci clean test jacoco:report - Create -javadoc.jar:
mvn javadoc:jar - Create -source.jar:
mvn source:jar
Contributing
Currently, there are two significant branches:
main(represents a stream of work leading to the release of a new major version)version/1.x(historical work that went into1.0.0-alpha-3, treat it as read-only - will be kept around for cherry-picking)
A small number of users have reported problems building Vavr. Read our contribution guide for details.
File: vavr/src/main/java/io/vavr/collection/readme-contributing.md
We need to follow some conventions to keep the collections consistent.
There are two kinds of methods
Accessors access some of the elements of a collection, but return a result which is unrelated to the collection.
Example of accessors are: head, foldLeft, toList.Transformers access elements of a collection and produce a new collection of same type as a result.
Example of transformers are: filter, map, groupBy, zip.
Given this, our transformers should return the most specific type, e.g. HashMap.map(...) should return HashMap. E.g. zipWithIndex is also a transformer.
Our accessors should return an interface instead to keep our library extensible for future enhancements. E.g. HashMap.groupBy should return Map because we may decide in future that returning another Map implementation than HashMap is more efficient. Returning now HashMap would break API on future changes. The only disadvantage is that Map's methods have generic parameters with wildcards, which reduces usability slightly.
More specific, methods like Seq.combinations() or Seq.crossProduct() should return Seq. This applies also to subclasses of Seq. E.g. CharSeq.combinations() should also return Seq. Of course the concrete object returned remains Vector (for CharSeq).
File: vavr/src/main/java/io/vavr/concurrent/readme-contributing.md
These are the ideas behind the implementation of Future/Promise:
The design follows separation of concerns in two manners:
- public interfaces vs. internal implementations (Promise/PromiseImpl, Future/FutureImpl)
- Future = read-only, Promise = write-once
Interfaces vs. internal classes
Concurrent programming is all about synchronized state. To keep this as simple as possible, it is a good idea to
separate readable and writable state. The internal implementations encapsulate the state. Their number of methods
drill down to those which access instance variables. These classes are typically very short. They represent a
clean and easy to maintain, thread-safe core.
The interfaces define, beside abstract methods, static factory methods, static extension methods and default methods.
The default implementations are built on top of the tread-safe core mentioned above. Typically, no additional
synchronization takes place here.
Read-only vs. write-once
Separating the end-user API into the Future interface, providing the read-only API, and the Promise interface,
providing the write-once API, solves a different concurrency problem than state synchronization. By separating
these concerns, we define a specific programming model that allows us to easily deal with common tasks in
concurrent programming.
final Promise<String> promise = Promise.make();
final Future<String> future = promise.future();
// producer
Future.run(() -> {
promise.success(produceSomething());
continueDoingSomethingUnrelated();
});
// consumer
Future.run(() -> {
startDoingSomething();
future.onSuccess(doSomethingWithResult);
});