Attempts
Fluent functional container for handling nullable values with validation pipelines
Attempts in BoxLang are an enhanced Java Optional that provides a fluent, functional approach to handling nullable values. Think of an Attempt as a smart container that can hold a value or be empty, with powerful methods for safely working with that value without null pointer exceptions.
Key Benefits: Attempts eliminate verbose null checks, enable declarative validation pipelines, and make your code more readable and maintainable through functional chaining patterns.
🌟 Why Use Attempts?
Attempts provide several advantages over traditional null handling:
✅ Eliminate null checks - No more
if (isNull(value))everywhere✅ Fluent API - Chain operations naturally:
.map().filter().orElse()✅ Built-in validation - Attach validation rules to create pipelines
✅ Immutable - Chain methods without mutating original values
✅ Functional programming - Write declarative, composable code
✅ Error handling - Convert missing values to exceptions or defaults gracefully
Traditional vs Attempt Approach
// ❌ Traditional approach - verbose and error-prone
user = userService.get( rc.id );
if ( isNull( user ) ) {
throw( "UserNotFoundException" );
}
email = user.getEmail();
if ( isNull( email ) ) {
throw( "Email not found" );
}
domain = email.listLast( "@" );
// ✅ Attempt approach - clean and declarative
attempt( userService.get( rc.id ) )
.flatMap( user -> user.getEmail() )
.map( email -> email.listLast( "@" ) )
.ifPresentOrElse(
domain -> println( "Domain: #domain#" ),
() -> throw( "User or email not found" )
);Attempts are also unmodifiable, so you can chain methods to handle the value more functionally, but it never mutates the original value. It can also be seeded with validation information to create validation pipelines.
💻 Attempts in Code
Let's see practical examples of Attempts in action:
🔄 Attempt States
An Attempt can exist in only two states:
State Checking Methods
isEmpty()
boolean
✅ Core check - true if no value present
isPresent()
boolean
✅ Core check - true if value exists
isNull()
boolean
🔍 Value check - true if value is null
hasFailed()
boolean
📝 Alias for isEmpty() - more readable for error handling
wasSuccessful()
boolean
📝 Alias for isPresent() - more readable for success cases
Rules for Present State
An attempt is present if and only if:
✅ The value is not null
An attempt is empty if:
❌ The value is null
❌ Created with
attempt()(no arguments)
Examples
Important: Only null makes an attempt empty. Empty strings, zero, false, and empty arrays/structs are all present values!
🏗️ Creating Attempts
Create attempts using the attempt() BIF (Built-In Function).
Empty Attempt
Create an empty attempt by calling attempt() with no arguments:
Attempt with Value
Pass any value or expression to create an attempt that may be present or empty:
Creation Patterns
🛠️ Working with Attempts
Once you have an attempt, you can interact with it using a rich set of fluent methods. These methods fall into several categories:
🔗 Related Documentation
Conditionals - Control flow and logical operators
Exception Management - Error handling and try/catch
Null and Nothingness - Understanding null values in BoxLang
Closures - Lambda expressions and functional programming
Operators - Elvis operator and safe navigation
isValid() BIF - Type validation reference
🎓 Summary
The Attempt class is BoxLang's answer to safe optional value handling with built-in validation. It provides:
✅ Null Safety - Eliminates null pointer errors
✅ Validation - Built-in type and custom validation rules
✅ Fluent API - Chainable operations for clean code
✅ Functional Style - Map, filter, flatMap for transformations
✅ Explicit Handling - Forces you to think about empty cases
✅ Composability - Easily combine with other attempts
Use attempts whenever you're dealing with values that might not exist or might be invalid, and let the type system guide you to handle both cases correctly.
Pro Tip: Start using attempts for API calls, database queries, and configuration lookups. Once you're comfortable, expand usage to form validation and data transformation pipelines.
Last updated
Was this helpful?
