Skip to content

Latest commit

 

History

History
246 lines (168 loc) · 12.4 KB

index.md

File metadata and controls

246 lines (168 loc) · 12.4 KB
title description image
Lazy Results
Result-Lazy provides lazy versions of Result objects

Lazy Results

This library provides lazy versions of Result objects.

Lazy results optimize performance by deferring costly operations until absolutely necessary. They behave like regular results, but only execute the underlying operation when an actual check for success or failure is performed.

Adding Lazy Results to Your Build

Artifact coordinates:

  • Group ID: com.leakyabstractions
  • Artifact ID: result-lazy
  • Version: {{ site.current_version }}

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

Creating Lazy Results

We can use LazyResults::ofSupplier to create a lazy result.

{% include_relative result-lazy/src/test/java/example/Fragments.java fragment="creation" %}

While suppliers can return a fixed success or failure, lazy results shine when they encapsulate time-consuming or resource-intensive operations.

{% include_relative result-lazy/src/test/java/example/Fragments.java fragment="expensive_calculation" %}

This sample method simply increments and returns a counter for brevity. However, in a typical scenario, this would involve an I/O operation.

Skipping Expensive Calculations

The advantage of lazy results is that they defer invoking the provided Supplier for as long as possible. Despite this, you can screen and transform them like any other result without losing their laziness.

{% include_relative result-lazy/src/test/java/example/Example_Test.java test="should_skip_expensive_calculation" %}

In this example, the expensive calculation is omitted because the lazy result is never fully evaluated. This test demonstrates that a lazy result can be transformed while maintaining laziness, ensuring that the expensive calculation is deferred.

These methods will preserve laziness:

Triggering Result Evaluation

Finally, when it's time to check whether the operation succeeds or fails, the lazy result will execute it. This is triggered by using any of the terminal methods, such as Result::hasSuccess.

{% include_relative result-lazy/src/test/java/example/Example_Test.java test="should_execute_expensive_calculation" %}

Here, the expensive calculation is executed because the lazy result is finally evaluated.

Terminal methods will immediately evaluate the lazy result:

Handling Success and Failure Eagerly

By default, Result::ifSuccess, Result::ifFailure, and Result::ifSuccessOrElse are treated as terminal methods. This means they eagerly evaluate the result and then perform an action based on its status.

{% include_relative result-lazy/src/test/java/example/Example_Test.java test="should_handle_success_eagerly" %}

In this test, we don't explicitly unwrap the value or check the status, but since we want to consume the success value, we need to evaluate the lazy result first.

Furthermore, even if we wanted to handle the failure scenario, we would still need to evaluate the lazy result.

{% include_relative result-lazy/src/test/java/example/Example_Test.java test="should_handle_failure_eagerly" %}

In this other test, we use Result::ifFailure instead of Result::ifSuccess. Since the lazy result is evaluated to a success, the failure consumer is never executed.

These methods are treated as terminal when used with regular consumer functions:

Handling Success and Failure Lazily

When these conditional actions may also be skipped along with the expensive calculation, we can encapsulate them into a LazyConsumer instead of a regular Consumer. All we need to do is to create the consumer using LazyConsumer::of. Lazy consumers will preserve the laziness until a terminal method is eventually used on the result.

{% include_relative result-lazy/src/test/java/example/Example_Test.java test="should_handle_success_lazily" %}

Here, we use a lazy consumer with Result::ifSuccess so the expensive calculation is skipped because the lazy result is never fully evaluated.

The full source code for the examples is available on GitHub.

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:

  • Commercial Use: You may use this library and derivatives for commercial purposes.
  • Modification: You may modify this library.
  • Distribution: You may distribute this library.
  • Patent Use: This license provides an express grant of patent rights from contributors.
  • Private Use: You may use and modify this library without distributing it.

Required:

  • License and Copyright Notice: If you distribute this library you must include a copy of the license and copyright notice.
  • State Changes: If you modify and distribute this library you must document changes made to this library.

Forbidden:

  • Trademark use: This license does not grant any trademark rights.
  • Liability: The library author cannot be held liable for damages.
  • Warranty: This library is provided without any warranty.