diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63f07aa..4ddeb3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,8 @@ Possible log types:
## [Unreleased]
+- `[added]` Add `inspect()` and `inspect_err()` methods (#185)
+
## [0.16.1] - 2024-02-29
- `[fixed]` PyPI not showing description (#176)
diff --git a/docs/result.md b/docs/result.md
index e3ee642..731c1f1 100644
--- a/docs/result.md
+++ b/docs/result.md
@@ -13,7 +13,7 @@
---
-
+
## function `as_result`
@@ -30,7 +30,7 @@ Regular return values are turned into ``Ok(return_value)``. Raised exceptions of
---
-
+
## function `as_async_result`
@@ -45,7 +45,7 @@ Make a decorator to turn an async function into one that returns a ``Result``. R
---
-
+
## function `is_ok`
@@ -68,7 +68,7 @@ elif is_err(r):
---
-
+
## function `is_err`
@@ -91,7 +91,7 @@ elif is_err(r):
---
-
+
## function `do`
@@ -128,7 +128,7 @@ NOTE: If you exclude the type annotation e.g. `Result[float, int]` your type che
---
-
+
## function `do_async`
@@ -278,6 +278,30 @@ Raise an UnwrapError since this type is `Ok`
---
+
+
+### method `inspect`
+
+```python
+inspect(op: 'Callable[[T], None]') → Result[T, E]
+```
+
+Calls a function with the contained value if `Ok`. Returns the original result.
+
+---
+
+
+
+### method `inspect_err`
+
+```python
+inspect_err(op: 'Callable[[E], None]') → Result[T, E]
+```
+
+Calls a function with the contained value if `Err`. Returns the original result.
+
+---
+
### method `is_err`
@@ -451,12 +475,12 @@ Return the value.
---
-
+
## class `DoException`
This is used to signal to `do()` that the result is an `Err`, which short-circuits the generator and returns that Err. Using this exception for control flow in `do()` allows us to simulate `and_then()` in the Err case: namely, we don't call `op`, we just return `self` (the Err).
-
+
### method `__init__`
@@ -474,12 +498,12 @@ __init__(err: 'Err[E]') → None
---
-
+
## class `Err`
A value that signifies failure and which stores arbitrary data for the error.
-
+
### method `__init__`
@@ -510,7 +534,7 @@ Return the inner value.
---
-
+
### method `and_then`
@@ -522,7 +546,7 @@ The contained result is `Err`, so return `Err` with the original value
---
-
+
### method `and_then_async`
@@ -534,7 +558,7 @@ The contained result is `Err`, so return `Err` with the original value
---
-
+
### method `err`
@@ -546,7 +570,7 @@ Return the error.
---
-
+
### method `expect`
@@ -558,7 +582,7 @@ Raises an `UnwrapError`.
---
-
+
### method `expect_err`
@@ -570,7 +594,31 @@ Return the inner value
---
-
+
+
+### method `inspect`
+
+```python
+inspect(op: 'Callable[[T], None]') → Result[T, E]
+```
+
+Calls a function with the contained value if `Ok`. Returns the original result.
+
+---
+
+
+
+### method `inspect_err`
+
+```python
+inspect_err(op: 'Callable[[E], None]') → Result[T, E]
+```
+
+Calls a function with the contained value if `Err`. Returns the original result.
+
+---
+
+
### method `is_err`
@@ -584,7 +632,7 @@ is_err() → Literal[True]
---
-
+
### method `is_ok`
@@ -598,7 +646,7 @@ is_ok() → Literal[False]
---
-
+
### method `map`
@@ -610,7 +658,7 @@ Return `Err` with the same value
---
-
+
### method `map_async`
@@ -622,7 +670,7 @@ The contained result is `Ok`, so return the result of `op` with the original val
---
-
+
### method `map_err`
@@ -634,7 +682,7 @@ The contained result is `Err`, so return `Err` with original error mapped to a n
---
-
+
### method `map_or`
@@ -646,7 +694,7 @@ Return the default value
---
-
+
### method `map_or_else`
@@ -658,7 +706,7 @@ Return the result of the default operation
---
-
+
### method `ok`
@@ -670,7 +718,7 @@ Return `None`.
---
-
+
### method `or_else`
@@ -682,7 +730,7 @@ The contained result is `Err`, so return the result of `op` with the original va
---
-
+
### method `unwrap`
@@ -694,7 +742,7 @@ Raises an `UnwrapError`.
---
-
+
### method `unwrap_err`
@@ -706,7 +754,7 @@ Return the inner value
---
-
+
### method `unwrap_or`
@@ -718,7 +766,7 @@ Return `default`.
---
-
+
### method `unwrap_or_else`
@@ -730,7 +778,7 @@ The contained result is ``Err``, so return the result of applying ``op`` to the
---
-
+
### method `unwrap_or_raise`
@@ -743,14 +791,14 @@ The contained result is ``Err``, so raise the exception with the value.
---
-
+
## class `UnwrapError`
Exception raised from ``.unwrap_<...>`` and ``.expect_<...>`` calls.
The original ``Result`` can be accessed via the ``.result`` attribute, but this is not intended for regular use, as type information is lost: ``UnwrapError`` doesn't know about both ``T`` and ``E``, since it's raised from ``Ok()`` or ``Err()`` which only knows about either ``T`` or ``E``, not both.
-
+
### method `__init__`
diff --git a/src/result/result.py b/src/result/result.py
index 06b78b9..30bf9a8 100644
--- a/src/result/result.py
+++ b/src/result/result.py
@@ -202,6 +202,19 @@ def or_else(self, op: object) -> Ok[T]:
"""
return self
+ def inspect(self, op: Callable[[T], Any]) -> Result[T, E]:
+ """
+ Calls a function with the contained value if `Ok`. Returns the original result.
+ """
+ op(self._value)
+ return self
+
+ def inspect_err(self, op: Callable[[E], Any]) -> Result[T, E]:
+ """
+ Calls a function with the contained value if `Err`. Returns the original result.
+ """
+ return self
+
class DoException(Exception):
"""
@@ -394,6 +407,19 @@ def or_else(self, op: Callable[[E], Result[T, F]]) -> Result[T, F]:
"""
return op(self._value)
+ def inspect(self, op: Callable[[T], Any]) -> Result[T, E]:
+ """
+ Calls a function with the contained value if `Ok`. Returns the original result.
+ """
+ return self
+
+ def inspect_err(self, op: Callable[[E], Any]) -> Result[T, E]:
+ """
+ Calls a function with the contained value if `Err`. Returns the original result.
+ """
+ op(self._value)
+ return self
+
# define Result as a generic type alias for use
# in type annotations
diff --git a/tests/test_result.py b/tests/test_result.py
index f0e05c6..c99c241 100644
--- a/tests/test_result.py
+++ b/tests/test_result.py
@@ -213,6 +213,36 @@ def test_and_then() -> None:
assert Err(3).and_then(sq_lambda).and_then(sq_lambda).err() == 3
+def test_inspect() -> None:
+ oks: list[int] = []
+ add_to_oks: Callable[[int], None] = lambda x: oks.append(x)
+
+ assert Ok(2).inspect(add_to_oks) == Ok(2)
+ assert Err("e").inspect(add_to_oks) == Err("e")
+ assert oks == [2]
+
+
+def test_inspect_err() -> None:
+ errs: list[str] = []
+ add_to_errs: Callable[[str], None] = lambda x: errs.append(x)
+
+ assert Ok(2).inspect_err(add_to_errs) == Ok(2)
+ assert Err("e").inspect_err(add_to_errs) == Err("e")
+ assert errs == ["e"]
+
+
+def test_inspect_regular_fn() -> None:
+ oks: list[str] = []
+
+ def _add_to_oks(x: str) -> str:
+ oks.append(x)
+ return x + x
+
+ assert Ok("hello").inspect(_add_to_oks) == Ok("hello")
+ assert Err("error").inspect(_add_to_oks) == Err("error")
+ assert oks == ["hello"]
+
+
@pytest.mark.asyncio
async def test_and_then_async() -> None:
assert (await (await Ok(2).and_then_async(sq_async)).and_then_async(sq_async)).ok() == 16