Skip to content

OptionType

Bases: Pipeable

OptionType is the common interface for an optional value.

Option[T] is the union of Some[T] and Null[T], and represents a value that can only have two states:

  • Some(value)
  • Null().

This is a common type in Rust, and is used to represent values that may be absent.

In python, this is best tought of a an union type T | None, but with additional methods to operate on the contained value in a functional style.

Option[T] and/or T | None types are very useful, as they have a number of uses:

  • Initial values
  • Union types
  • Return value where None is returned on error
  • Optional class fields
  • Optional function arguments

The fact that T | None is a very common pattern in python, but without a dedicated structure/handling, leads to:

  • a lot of boilerplate code
  • potential bugs (even with type checkers)
  • less readable code (where does the None come from? is it expected?).

Option[T] instances are commonly paired with pattern matching. This allow to query the presence of a value and take action, always accounting for the None case.

Example:

>>> from pyochain import Option, Some, Null
>>> def divide(a: int, b: int) -> Option[int]:
...     if b == 0:
...         return Null()
...     return Some(a // b)
>>>
>>> divide(10, 2)
Some(5)
>>> divide(10, 0)
NONE

__bool__()

Prevent implicit Some|None value checking in boolean contexts.

Raises:

Type Description
TypeError

Always, to prevent implicit Some|None value checking.

Example:

>>> from pyochain import Some
>>> x = Some(42)
>>> bool(x)
Traceback (most recent call last):
...
TypeError: Option instances cannot be used in boolean contexts for implicit `Some|None` value checking. Use is_some() or is_none() instead.

__eq__(other)

Checks if this Option and other are equal.

A plain Python None is considered equal to a pyochain.Null instance.

Parameters:

Name Type Description Default
other object

The other object to compare with.

required

Returns:

Name Type Description
bool bool

True if both instances are equal, False otherwise.

See Also
  • Option.eq for a type-safe, performant version that only accepts Option[T] instances.

Example:

>>> from pyochain import Some, NONE
>>> Some(42) == Some(42)
True
>>> Some(42) == Some(21)
False
>>> Some(42) == NONE
False
>>> NONE == NONE
True
>>> NONE == None
True
>>> Some(42) == 42
False

and_(optb)

Returns NONE if the option is NONE, otherwise returns optb.

This is similar to and_then, except that the value is passed directly instead of through a closure.

Parameters:

Name Type Description Default
optb Option[U]

The option to return if the original option is NONE

required

Returns: Option[U]: NONE if the original option is NONE, otherwise optb.

Example:

>>> from pyochain import Some, NONE
>>> Some(2).and_(NONE)
NONE
>>> NONE.and_(Some("foo"))
NONE
>>> Some(2).and_(Some("foo"))
Some('foo')
>>> NONE.and_(NONE)
NONE

and_then(f, *args, **kwargs)

Calls a function if the option is Some, otherwise returns None.

Parameters:

Name Type Description Default
f Callable[Concatenate[T, P], Option[R]]

The function to call with the Some value.

required
*args P.args

Additional positional arguments to pass to f.

()
**kwargs P.kwargs

Additional keyword arguments to pass to f.

{}

Returns:

Type Description
Option[R]

Option[R]: The result of the function if Some, otherwise None.

Example:

>>> from pyochain import Some, NONE
>>> def sq(x: int) -> Option[int]:
...     return Some(x * x)
>>> def nope(x: int) -> Option[int]:
...     return NONE
>>> Some(2).and_then(sq).and_then(sq)
Some(16)
>>> Some(2).and_then(sq).and_then(nope)
NONE
>>> Some(2).and_then(nope).and_then(sq)
NONE
>>> NONE.and_then(sq).and_then(sq)
NONE

and_then_star(func)

and_then_star(
    func: Callable[[Any], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3, T4], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3, T4, T5], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3, T4, T5, T6], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3, T4, T5, T6, T7], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[
        [T1, T2, T3, T4, T5, T6, T7, T8], Option[R]
    ],
) -> Option[R]
and_then_star(
    func: Callable[
        [T1, T2, T3, T4, T5, T6, T7, T8, T9], Option[R]
    ],
) -> Option[R]
and_then_star(
    func: Callable[
        [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], Option[R]
    ],
) -> Option[R]

Calls a function if the option is Some, unpacking the iterable into the function.

Parameters:

Name Type Description Default
func Callable[..., Option[R]]

The function to call with the unpacked Some value.

required

Returns:

Type Description
Option[R]

Option[R]: The result of the function if Some, otherwise None.

Example:

>>> from pyochain import Some, NONE
>>> Some((2, 3)).and_then_star(lambda x, y: Some(x + y))
Some(5)
>>> NONE.and_then_star(lambda x, y: Some(x + y))
NONE

eq(other)

Checks if two Option[T] instances are equal.

Note

This method behave similarly to __eq__, but only accepts Option[T] instances as argument.

This avoids runtime isinstance checks (we check for boolean is_some(), which is a simple function call), and is more type-safe.

Parameters:

Name Type Description Default
other Option[T]

The other Option[T] instance to compare with.

required

Returns:

Name Type Description
bool bool

True if both instances are equal, False otherwise.

Example:

>>> from pyochain import Some, NONE
>>> Some(42).eq(Some(42))
True
>>> Some(42).eq(Some(21))
False
>>> Some(42).eq(NONE)
False
>>> NONE.eq(NONE)
True

expect(msg)

Returns the contained Some value.

Raises an exception with a provided message if the value is None.

Parameters:

Name Type Description Default
msg str

The message to include in the exception if the result is None.

required

Returns:

Name Type Description
T T

The contained Some value.

Raises:

Type Description
OptionUnwrapError

If the result is None.

Example:

>>> from pyochain import Some, NONE
>>> Some("value").expect("fruits are healthy")
'value'
>>> NONE.expect("fruits are healthy")
Traceback (most recent call last):
...
OptionUnwrapError: fruits are healthy (called `expect` on a `None`)

filter(predicate, *args, **kwargs)

Returns None if the option is None, otherwise calls predicate with the wrapped value.

This function works similar to Iter.filter in the sense that we only keep the value if it matches a predicate.

You can imagine the Option[T] being an iterator over one or zero elements.

Parameters:

Name Type Description Default
predicate Callable[Concatenate[T, P], R]

The predicate to apply to the contained value.

required
*args P.args

Additional positional arguments to pass to predicate.

()
**kwargs P.kwargs

Additional keyword arguments to pass to predicate.

{}

Returns:

Type Description
Option[T]

Option[T]: Some[T] if predicate returns true (where T is the wrapped value), NONE if predicate returns false.

Example:

>>> from pyochain import Some, NONE
>>>
>>> def is_even(n: int) -> bool:
...     return n % 2 == 0
>>>
>>> NONE.filter(is_even)
NONE
>>> Some(3).filter(is_even)
NONE
>>> Some(4).filter(is_even)
Some(4)

flatten()

Flattens a nested Option.

Converts an Option[Option[U]] into an Option[U] by removing one level of nesting.

Equivalent to Option.and_then(lambda x: x).

Returns:

Type Description
Option[U]

Option[U]: The flattened option.

Example:

>>> from pyochain import Some, NONE
>>> Some(Some(42)).flatten()
Some(42)
>>> Some(NONE).flatten()
NONE
>>> NONE.flatten()
NONE

inspect(f, *args, **kwargs)

Applies a function to the contained Some value, returning the original Option.

This allows side effects (logging, debugging, metrics, etc.) on the wrapped value without changing it.

Parameters:

Name Type Description Default
f Callable[Concatenate[T, P], object]

Function to apply to the Some value.

required
*args P.args

Additional positional arguments to pass to f.

()
**kwargs P.kwargs

Additional keyword arguments to pass to f.

{}

Returns:

Type Description
Option[T]

Option[T]: The original option, unchanged.

Example:

>>> from pyochain import Some, NONE, Vec
>>> seen = Vec[int](())
>>> Some(2).inspect(lambda x: seen.append(x))
Some(2)
>>> seen
Vec(2)
>>> NONE.inspect(lambda x: seen.append(x))
NONE
>>> seen
Vec(2)

is_none()

Returns True if the option is a None value.

Returns:

Name Type Description
bool bool

True if the option is a _None variant, False otherwise.

Example:

>>> from pyochain import Some, NONE
>>> x: Option[int] = Some(2)
>>> x.is_none()
False
>>> y: Option[int] = NONE
>>> y.is_none()
True

is_none_or(func, *args, **kwargs)

Returns true if the option is a None or the value inside of it matches a predicate.

Parameters:

Name Type Description Default
func Callable[Concatenate[T, P], bool]

The predicate to apply to the contained value.

required
*args P.args

Additional positional arguments to pass to func.

()
**kwargs P.kwargs

Additional keyword arguments to pass to func.

{}

Returns:

Name Type Description
bool bool

True if the option is None or the predicate returns True for the contained value, False otherwise.

Example:

>>> from pyochain import Some, NONE
>>> Some(2).is_none_or(lambda x: x > 1)
True
>>> Some(0).is_none_or(lambda x: x > 1)
False
>>> NONE.is_none_or(lambda x: x > 1)
True
>>> Some("hello").is_none_or(lambda x: len(x) > 1)
True

is_some()

Returns True if the option is a Some value.

Returns:

Name Type Description
bool bool

True if the option is a Some variant, False otherwise.

Example:

>>> from pyochain import Some, NONE
>>> x: Option[int] = Some(2)
>>> x.is_some()
True
>>> y: Option[int] = NONE
>>> y.is_some()
False

is_some_and(predicate, *args, **kwargs)

Returns true if the option is a Some and the value inside of it matches a predicate.

Parameters:

Name Type Description Default
predicate Callable[Concatenate[T, P], bool]

The predicate to apply to the contained value.

required
*args P.args

Additional positional arguments to pass to predicate.

()
**kwargs P.kwargs

Additional keyword arguments to pass to predicate.

{}

Returns:

Name Type Description
bool bool

True if the option is Some and the predicate returns True for the contained value, False otherwise.

Example:

>>> from pyochain import Some, NONE
>>> x = Some(2)
>>> x.is_some_and(lambda x: x > 1)
True

>>> x = Some(0)
>>> x.is_some_and(lambda x: x > 1)
False
>>> x = NONE
>>> x.is_some_and(lambda x: x > 1)
False
>>> x = Some("hello")
>>> x.is_some_and(lambda x: len(x) > 1)
True

iter()

Creates an Iter over the optional value.

  • If the option is Some(value), the iterator yields value.
  • If the option is NONE, the iterator yields nothing.

Equivalent to Iter((self,)).

Returns:

Type Description
Iter[T]

Iter[T]: An iterator over the optional value.

Example:

>>> from pyochain import Some, NONE
>>> Some(42).iter().next()
Some(42)
>>> NONE.iter().next()
NONE

map(f, *args, **kwargs)

Maps an Option[T] to Option[U].

Done by applying a function to a contained Some value, leaving a None value untouched.

Parameters:

Name Type Description Default
f Callable[Concatenate[T, P], R]

The function to apply to the Some value.

required
*args P.args

Additional positional arguments to pass to f.

()
**kwargs P.kwargs

Additional keyword arguments to pass to f.

{}

Returns:

Type Description
Option[R]

Option[R]: A new Option with the mapped value if Some, otherwise None.

Example:

>>> from pyochain import Some, NONE
>>> Some("Hello, World!").map(len)
Some(13)
>>> NONE.map(len)
NONE

map_or(default, f, *args, **kwargs)

Returns the result of applying a function to the contained value if Some, otherwise returns the default value.

Parameters:

Name Type Description Default
default R

The default value to return if NONE.

required
f Callable[Concatenate[T, P], R]

The function to apply to the contained value.

required
*args P.args

Additional positional arguments to pass to f.

()
**kwargs P.kwargs

Additional keyword arguments to pass to f.

{}

Returns:

Name Type Description
R R

The result of f(self.unwrap()) if Some, otherwise default.

Example:

>>> from pyochain import Some, NONE
>>> Some(2).map_or(0, lambda x: x * 10)
20
>>> NONE.map_or(0, lambda x: x * 10)
0

map_or_else(default, f)

Returns the result of applying a function to the contained value if Some, otherwise computes a default value.

Parameters:

Name Type Description Default
default Callable[[], R]

A function returning the default value if NONE.

required
f Callable[[T], R]

The function to apply to the contained value.

required

Returns:

Name Type Description
R R

The result of f(self.unwrap()) if Some, otherwise default().

Example:

>>> from pyochain import Some, NONE
>>> Some(2).map_or_else(lambda: 0, lambda x: x * 10)
20
>>> NONE.map_or_else(lambda: 0, lambda x: x * 10)
0

map_star(func)

map_star(func: Callable[[Any], R]) -> Option[R]
map_star(func: Callable[[T1, T2], R]) -> Option[R]
map_star(func: Callable[[T1, T2, T3], R]) -> Option[R]
map_star(func: Callable[[T1, T2, T3, T4], R]) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5], R],
) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5, T6], R],
) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5, T6, T7], R],
) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5, T6, T7, T8], R],
) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5, T6, T7, T8, T9], R],
) -> Option[R]
map_star(
    func: Callable[
        [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], R
    ],
) -> Option[R]

Maps an Option[Iterable] to Option[U] by unpacking the iterable into the function.

Done by applying a function to a contained Some value, leaving a None value untouched.

Parameters:

Name Type Description Default
func Callable[..., R]

The function to apply to the unpacked Some value.

required

Returns:

Type Description
Option[R]

Option[R]: A new Option with the mapped value if Some, otherwise None.

Example:

>>> from pyochain import Some, NONE
>>> Some((2, 3)).map_star(lambda x, y: x + y)
Some(5)
>>> NONE.map_star(lambda x, y: x + y)
NONE

ne(other)

Checks if two Option[T] instances are not equal.

Parameters:

Name Type Description Default
other Option[T]

The other Option[T] instance to compare with.

required

Returns:

Name Type Description
bool bool

True if both instances are not equal, False otherwise.

Example:

>>> from pyochain import Some, NONE
>>> Some(42).ne(Some(21))
True
>>> Some(42).ne(Some(42))
False
>>> Some(42).ne(NONE)
True
>>> NONE.ne(NONE)
False

ok_or(err)

Converts the option to a Result.

Parameters:

Name Type Description Default
err E

The error value to use if the option is NONE.

required

Returns:

Type Description
Result[T, E]

Result[T, E]: Ok(v) if Some(v), otherwise Err(err).

Example:

>>> from pyochain import Some, NONE
>>> Some(1).ok_or("fail")
Ok(1)
>>> NONE.ok_or("fail")
Err('fail')

ok_or_else(err)

Converts the option to a Result.

Parameters:

Name Type Description Default
err Callable[[], E]

A function returning the error value if the option is NONE.

required

Returns:

Type Description
Result[T, E]

Result[T, E]: Ok(v) if Some(v), otherwise Err(err()).

Example:

>>> from pyochain import Some, NONE
>>> Some(1).ok_or_else(lambda: "fail")
Ok(1)
>>> NONE.ok_or_else(lambda: "fail")
Err('fail')

or_(optb)

Returns the option if it contains a value, otherwise returns optb.

Parameters:

Name Type Description Default
optb Option[T]

The option to return if the original option is NONE.

required

Returns:

Type Description
Option[T]

Option[T]: The original option if it is Some, otherwise optb.

Example:

>>> from pyochain import Some, NONE
>>> Some(2).or_(NONE)
Some(2)
>>> NONE.or_(Some(100))
Some(100)
>>> Some(2).or_(Some(100))
Some(2)
>>> NONE.or_(NONE)
NONE

or_else(f)

Returns the Option[T] if it contains a value, otherwise calls a function and returns the result.

Parameters:

Name Type Description Default
f Callable[[], Option[T]]

The function to call if the option is None.

required

Returns:

Type Description
Option[T]

Option[T]: The original Option if it is Some, otherwise the result of the function.

Example:

>>> from pyochain import Some, NONE
>>> def nobody() -> Option[str]:
...     return NONE
>>> def vikings() -> Option[str]:
...     return Some("vikings")
>>> Some("barbarians").or_else(vikings)
Some('barbarians')
>>> NONE.or_else(vikings)
Some('vikings')
>>> NONE.or_else(nobody)
NONE

reduce(other, func)

Reduces two options into one, using the provided function if both are Some.

If self is Some(s) and other is Some(o), this method returns Some(func(s, o)).

Otherwise, if only one of self and other is Some, that value is returned.

If both self and other are NONE, NONE is returned.

Parameters:

Name Type Description Default
other Option[T]

The second option.

required
func Callable[[T, T], T]

The function to apply to the unwrapped values.

required

Returns:

Type Description
Option[T]

Option[T]: The resulting option after reduction.

Example:

>>> from pyochain import Some, NONE
>>> s12 = Some(12)
>>> s17 = Some(17)
>>>
>>> def add(a: int, b: int) -> int:
...     return a + b
>>>
>>> s12.reduce(s17, add)
Some(29)
>>> s12.reduce(NONE, add)
Some(12)
>>> NONE.reduce(s17, add)
Some(17)
>>> NONE.reduce(NONE, add)
NONE

transpose()

Transposes an Option of a Result into a Result of an Option.

The mapping is as follows:

  • Some(Ok[T]) is mapped to Ok(Some[T])
  • Some(Err[E]) is mapped to Err[E]
  • NONE is mapped to Ok(NONE)

Returns:

Type Description
Result[Option[T], E]

Result[Option[T], E]: The transposed result.

Example:

>>> from pyochain import Some, Ok, Err, NONE
>>> Some(Ok(5)).transpose()
Ok(Some(5))
>>> NONE.transpose()
Ok(NONE)
>>> Some(Err("error")).transpose()
Err('error')

unwrap()

Returns the contained Some value.

Returns:

Name Type Description
T T

The contained Some value.

Raises:

Type Description
OptionUnwrapError

If the option is None.

Example:

>>> from pyochain import Some
>>> Some("car").unwrap()
'car'
>>> from pyochain import NONE
>>> NONE.unwrap()
Traceback (most recent call last):
...
OptionUnwrapError: called `unwrap` on a `None`

unwrap_or(default)

Returns the contained Some value or a provided default.

Parameters:

Name Type Description Default
default T

The value to return if the result is None.

required

Returns:

Name Type Description
T T

The contained Some value or the provided default.

Example:

>>> from pyochain import Some, NONE
>>> Some("car").unwrap_or("bike")
'car'
>>> NONE.unwrap_or("bike")
'bike'

unwrap_or_else(f)

Returns the contained Some value or computes it from a function.

Parameters:

Name Type Description Default
f Callable[[], T]

A function that returns a default value if the result is None.

required

Returns:

Name Type Description
T T

The contained Some value or the result of the function.

Example:

>>> from pyochain import Some, NONE
>>> k = 10
>>> Some(4).unwrap_or_else(lambda: 2 * k)
4
>>> NONE.unwrap_or_else(lambda: 2 * k)
20

unwrap_or_none()

Returns the contained Some value or None.

This is a convenience method for interoperability with APIs that use None to represent the absence of a value,

e.g. when interacting with standard Python libraries, or external dependencies.

This is NOT the recommended use for handling Option in any code that can be controlled, as it defeats the purpose of using Option for explicit handling of optional values.

Returns:

Type Description
T | None

T | None: The contained Some value or None.

Example:

>>> from pyochain import Option, Some, NONE
>>> NONE.unwrap_or_none() is None
True
>>> Some(42).unwrap_or_none()
42

unzip()

Unzips an Option of a tuple into a tuple of Options.

If the option is Some((a, b)), this method returns (Some(a), Some(b)). If the option is NONE, it returns (NONE, NONE).

Returns:

Type Description
tuple[Option[T], Option[U]]

tuple[Option[T], Option[U]]: A tuple containing two options.

Example:

>>> from pyochain import Some, NONE
>>> Some((1, "a")).unzip()
(Some(1), Some('a'))
>>> NONE.unzip()
(NONE, NONE)

xor(optb)

Returns Some if exactly one of self, optb is Some, otherwise returns NONE.

Parameters:

Name Type Description Default
optb Option[T]

The other option to compare with.

required

Returns:

Type Description
Option[T]

Option[T]: Some value if exactly one option is Some, otherwise NONE.

Example:

>>> from pyochain import Some, NONE
>>> Some(2).xor(NONE)
Some(2)
>>> NONE.xor(Some(2))
Some(2)
>>> Some(2).xor(Some(2))
NONE
>>> NONE.xor(NONE)
NONE

zip(other)

Returns an Option[tuple[T, U]] containing a tuple of the values if both options are Some, otherwise returns NONE.

Parameters:

Name Type Description Default
other Option[U]

The other option to zip with.

required

Returns:

Type Description
Option[tuple[T, U]]

Option[tuple[T, U]]: Some((self, other)) if both are Some, otherwise NONE.

Example:

>>> from pyochain import Some, NONE
>>> Some(1).zip(Some("a"))
Some((1, 'a'))
>>> Some(1).zip(NONE)
NONE
>>> NONE.zip(Some("a"))
NONE

zip_with(other, f)

Zips self and another Option with function f.

If self is Some(s) and other is Some(o), this method returns Some(f(s, o)).

Otherwise, NONE is returned.

Parameters:

Name Type Description Default
other Option[U]

The second option.

required
f Callable[[T, U], R]

The function to apply to the unwrapped values.

required

Returns:

Type Description
Option[R]

Option[R]: The resulting option after applying the function.

Example:

>>> from dataclasses import dataclass
>>> from pyochain import Some, NONE
>>>
>>> @dataclass
... class Point:
...     x: float
...     y: float
>>>
>>> x = Some(17.5)
>>> y = Some(42.7)
>>> x.zip_with(y, Point)
Some(Point(x=17.5, y=42.7))
>>> x.zip_with(NONE, Point)
NONE
>>> NONE.zip_with(y, Point)
NONE