Skip to content

Commit 3cbee91

Browse files
committed
Update README.md with async_option documentation
1 parent a25847d commit 3cbee91

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

README.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ on-demand as we go along.
129129
is amazing stuff.
130130
- **option** - an optional world for working with optional values.
131131
- **result** - an error handling world for working with result values.
132+
- **seq** - a world for working with sequences.
133+
- **async_result** - an asynchronous error handling world for working
134+
with asynchronous result values.
135+
- **async_option** - an asynchronous optional world for working with
136+
asynchronous optional values.
132137
- **Mailbox Processor**: for lock free programming using the [Actor
133138
model](https://en.wikipedia.org/wiki/Actor_model).
134139
- **Cancellation Token**: for cancellation of asynchronous (and
@@ -419,6 +424,135 @@ A simplified type called `Try` is also available. It's a result type that is
419424
pinned to `Exception` i.e., `Result[TSource, Exception]`.
420425

421426

427+
### AsyncResult
428+
429+
The `AsyncResult[T, TError]` type is the asynchronous version of `Result`. It allows you
430+
to compose asynchronous operations that may fail, using the Result type. This is
431+
particularly useful for handling errors in asynchronous code, such as API calls,
432+
database operations, or any other I/O-bound tasks.
433+
434+
Similar to the `Result` effect, AsyncResult enables "railway oriented programming" but
435+
for asynchronous operations. If any part of the function yields an `Error`, the function
436+
is short-circuited and the following statements will never be executed.
437+
438+
```python
439+
from collections.abc import AsyncGenerator
440+
441+
from expression import Error, Ok, effect
442+
443+
444+
@effect.async_result[int, str]()
445+
async def fn() -> AsyncGenerator[int, int]:
446+
x: int = yield 42 # Regular value
447+
y: int = yield await Ok(43) # Awaitable Ok value
448+
449+
# Short-circuit if condition is met
450+
if x + y > 80:
451+
z: int = yield await Error("Value too large") # This will short-circuit
452+
else:
453+
z: int = yield 44
454+
455+
yield x + y + z # Final value
456+
457+
458+
# This would be run in an async context
459+
# result = await fn()
460+
# assert result == Error("Value too large")
461+
```
462+
463+
AsyncResult works well with other async functions and can be nested:
464+
465+
466+
```python
467+
@effect.async_result[int, str]()
468+
async def inner(x: int) -> AsyncGenerator[int, int]:
469+
y: int = yield x + 1
470+
yield y + 1 # Final value is y + 1
471+
472+
473+
@effect.async_result[int, str]()
474+
async def outer() -> AsyncGenerator[int, int]:
475+
x: int = yield 40
476+
477+
# Call inner and await its result
478+
inner_result = await inner(x)
479+
y: int = yield await inner_result
480+
481+
yield y # Final value is y
482+
483+
484+
# This would be run in an async context
485+
# result = await outer()
486+
# assert result == Ok(42) # 40 -> 41 -> 42
487+
```
488+
489+
A simplified type called `AsyncTry` is also available. It's an async result type that is
490+
pinned to `Exception` i.e., `AsyncResult[TSource, Exception]`.
491+
492+
493+
### AsyncOption
494+
495+
The `AsyncOption[T]` type is the asynchronous version of `Option`. It allows you to
496+
compose asynchronous operations that may return an optional value, using the Option type.
497+
This is particularly useful for handling optional values in asynchronous code, such as
498+
API calls that might not return a value, database queries that might not find a record,
499+
or any other I/O-bound tasks that might not produce a meaningful result.
500+
501+
Similar to the `Option` effect, AsyncOption enables short-circuiting but for asynchronous
502+
operations. If any part of the function yields `Nothing`, the function is short-circuited
503+
and the following statements will never be executed.
504+
505+
```python
506+
from collections.abc import AsyncGenerator
507+
508+
from expression import Nothing, Some, effect
509+
510+
511+
@effect.async_option[int]()
512+
async def fn_option() -> AsyncGenerator[int, int]:
513+
x: int = yield 42 # Regular value
514+
y: int = yield await Some(43) # Awaitable Some value
515+
516+
# Short-circuit if condition is met
517+
if x + y > 80:
518+
z: int = yield await Nothing # This will short-circuit
519+
else:
520+
z: int = yield 44
521+
522+
yield x + y + z # Final value
523+
524+
525+
# This would be run in an async context
526+
# result = await fn_option()
527+
# assert result is Nothing
528+
```
529+
530+
AsyncOption works well with other async functions and can be nested:
531+
532+
533+
```python
534+
@effect.async_option[int]()
535+
async def inner_option(x: int) -> AsyncGenerator[int, int]:
536+
y: int = yield x + 1
537+
yield y + 1 # Final value is y + 1
538+
539+
540+
@effect.async_option[int]()
541+
async def outer_option() -> AsyncGenerator[int, int]:
542+
x: int = yield 40
543+
544+
# Call inner and await its result
545+
inner_result = await inner_option(x)
546+
y: int = yield await inner_result
547+
548+
yield y # Final value is y
549+
550+
551+
# This would be run in an async context
552+
# result = await outer_option()
553+
# assert result == Some(42) # 40 -> 41 -> 42
554+
```
555+
422556
### Sequence
423557

424558
Sequences is a thin wrapper on top of iterables and contains operations for working with

0 commit comments

Comments
 (0)