Lazy Results

Result-Lazy provides lazy versions of Result objects

Lazy Results

This library provides lazy versions of Result objects.

Lazy results encapsulate expensive operations that can be entirely omitted (as an optimization). These result can be manipulated just like any other, but the encapsulated operation will not be executed unless there’s an actual check for success/failure.

Adding Lazy Results to Your Build

Artifact coordinates:

Maven Central Repository provides snippets for different build tools to declare this dependency.

Creating Lazy Results

To create a lazy result, all we need to do is invoke static method LazyResults.ofSupplier():

/* Create new lazy result */
Supplier<Result<Integer, String>> supplier = () -> success(123);
Result<Integer, String> lazy = LazyResults.ofSupplier(supplier); // Just like that!

As you can see, a supplier can simply return a fixed result. However, lazy results are more useful when they encapsulate an actual method that either takes a long time to execute or potentially uses up scarce resources.

/* Represents the operation we could omit */
Result<Long, Exception> expensiveCalculation(AtomicLong timesExecuted) {
  long counter = timesExecuted.incrementAndGet();
  return success(counter);
} // In this example, we just increment and return current count

The good thing about lazy results is that they will try to defer the invocation of the given supplier as long as possible. You can manipulate them just like any other result, though.

/** The operation is omitted because the lazy result is not fully evaluated */
@Test
void should_not_execute_expensive_action() {
  final AtomicLong timesExecuted = new AtomicLong();
  // Given
  final Result<Long, Exception> lazy = LazyResults
      .ofSupplier(() -> expensiveCalculation(timesExecuted));
  // When
  final Result<String, Exception> transformed = lazy.mapSuccess(Object::toString);
  // Then
  assertNotNull(transformed);
  assertEquals(0L, timesExecuted.get());
} // End

The previous test proves that a lazy result could be transformed and it kept behaving as a lazy result, which means that the expensive calculation was never executed.

On the other hand, when it comes the time to evaluate whether the operation was actually successful or failed, the lazy result will end up invoking the method.

/** The operation is executed because the lazy result is evaluated */
@Test
void should_execute_expensive_action() {
  final AtomicLong timesExecuted = new AtomicLong();
  // Given
  final Result<Long, Exception> lazy = LazyResults
      .ofSupplier(() -> expensiveCalculation(timesExecuted));
  // When
  final Result<String, Exception> transformed = lazy.mapSuccess(Object::toString);
  final boolean success = transformed.hasSuccess();
  // Then
  assertTrue(success);
  assertEquals(1L, timesExecuted.get());
} // End

Additional Info

Releases

This library adheres to Pragmatic Versioning.

Artifacts are available in Maven Central.

Javadoc

Here you can find the full Javadoc documentation.

Looking for Support?

We’d love to help. Check out the support guidelines.

Contributions Welcome

If you’d like to contribute to this project, please start here.

Code of Conduct

This project is governed by the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.

Author

Copyright 2024 Guillermo Calvo.

License

This library is licensed under the Apache License, Version 2.0 (the “License”); you may not use it except in compliance with the License.

You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and limitations under the License.

Permitted:

Required:

Forbidden: