Option¶
See the original Rust documentation here.
patina.option |
Optional values. |
Option |
The Option type. |
Some (value) |
|
None_ |
Optional values.
Type Option represents an optional value: every Option is either
Some
and contains a value, or None_
, and does not.
Option types are very common in Rust code, as they have a number of uses:
- Initial values
- Return values for functions that are not defined over their entire input range (partial functions)
- Return value for otherwise reporting simple errors, where
None_
is returned on error - Optional struct fields
- Struct fields that can be loaned or “taken”
- Optional function arguments
- Nullable pointers
- Swapping things out of difficult situations
Options are commonly paired with pattern matching to query the presence of a
value and take action, always accounting for the None_
case.
>>> def divide(numerator: float, denominator: float) -> Option[float]:
... if denominator == 0.0:
... return None_()
... return Some(numerator / denominator)
...
>>> result = divide(2.0, 3.0)
>>>
>>> if result.is_some():
... print(f"Result: {result.unwrap()}")
... else:
... print(f"Cannot divide by 0")
...
Result: 0.6666666666666666
Examples¶
Basic pattern matching on Option
:
>>> msg = Some("howdy")
>>>
>>> if msg.is_some():
... print(msg.unwrap())
...
howdy
>>> unwrapped_msg = msg.unwrap_or("default message")
>>> unwrapped_msg
'howdy'
Initialize a result to None_
before a loop:
>>> from dataclasses import dataclass
>>>
>>> @dataclass
... class Kingdom:
... size: int
... name: str
...
>>> class PlantKingdom(Kingdom): pass
...
>>> class AnimalKingdom(Kingdom): pass
...
>>> all_the_big_things = [
... PlantKingdom(250, "redwood"),
... PlantKingdom(230, "noble fir"),
... PlantKingdom(229, "sugar pine"),
... AnimalKingdom(25, "blue whale"),
... AnimalKingdom(19, "fin whale"),
... AnimalKingdom(15, "north pacific right whale"),
... ]
>>>
>>> # We're going to search for the name of the biggest animal, but to start
>>> # with we've just got `None_`
>>> name_of_biggest_animal: Option[str] = None_()
>>> size_of_biggest_animal = 0
>>> for big_thing in all_the_big_things:
... if isinstance(big_thing, AnimalKingdom) \
... and big_thing.size > size_of_biggest_animal:
... size_of_biggest_animal = big_thing.size
... name_of_biggest_animal = Some(big_thing.name)
...
>>> if name_of_biggest_animal.is_some():
... print(f"the biggest animal is {name_of_biggest_animal.unwrap()}")
... else:
... print("there are no animals :(")
...
the biggest animal is blue whale
The Option Type¶
-
class
patina.option.
Option
¶ The
Option
type. See themodule-level documentation
for more.-
__bool__
() → bool¶ Returns
True
if the option is aSome
value, elseFalse
.>>> x: Option[int] = Some(0) >>> True if x else False True >>> y: Option[int] = None_() >>> True if y else False False
-
is_some
() → bool¶ Returns
True
if the option is aSome
value.>>> x: Option[int] = Some(2) >>> x.is_some() True >>> x: Option[int] = None_() >>> x.is_some() False
-
is_none
() → bool¶ Returns
True
if the option is aNone_
value.>>> x: Option[int] = Some(2) >>> x.is_none() False >>> x: Option[int] = None_() >>> x.is_none() True
-
expect
(msg: str) → T¶ Returns the contained
Some
value.Raises: AssertionError – Raised if the value is a None_
, with a custom message provided bymsg
.>>> x = Some("value") >>> x.expect("fruits are healthy") 'value' >>> x: Option[str] = None_() >>> x.expect("fruits are healthy") Traceback (most recent call last): ... AssertionError: fruits are healthy
-
unwrap
() → T¶ Returns the contained
Some
value.Because this function may panic, its use is generally discouraged. Instead, prefer to use pattern matching and handle the
None_
case explicitly, or callunwrap_or()
orunwrap_or_else()
.Raises: AssertionError – Raised if the self value is None_
.>>> x = Some("air") >>> x.unwrap() 'air' >>> x: Option[str] = None_() >>> x.unwrap() Traceback (most recent call last): ... AssertionError: called `Option.unwrap` on a `None_` value
-
unwrap_or
(default: T) → T¶ Returns the contained
Some
value or a provided default.Arguments passed to
unwrap_or
are eagerly evaluated; if you are passing the result of a function call, it is recommended to useunwrap_or_else()
, which is lazily evaluated.>>> Some("car").unwrap_or("bike") 'car' >>> None_[str]().unwrap_or("bike") 'bike'
-
unwrap_or_else
(f: Callable[[], T]) → T¶ Returns the contained
Some
value or computes it from a closure.>>> k = 10 >>> Some(4).unwrap_or_else(lambda: 2 * k) 4 >>> None_[int]().unwrap_or_else(lambda: 2 * k) 20
-
map
(f: Callable[[T], U]) → patina.option.Option[~U][U]¶ Maps an
Option[T]
toOption[U]
by applying a function to a contained value.Converting an
Option[str]
into anOption[int]
:>>> maybe_some_string = Some("Hello, World!") >>> maybe_some_len = maybe_some_string.map(len) >>> maybe_some_len Some(13)
-
map_or
(default: U, f: Callable[[T], U]) → U¶ Applies a function to the contained value (if any), or returns the provided default (if not).
Arguments passed to
map_or
are eagerly evaluated; if you are passing the result of a function call, it is recommended to usemap_or_else()
, which is lazily evaluated.>>> x = Some("foo") >>> x.map_or(42, len) 3 >>> x: Option[str] = None_() >>> x.map_or(42, len) 42
-
map_or_else
(default: Callable[[], U], f: Callable[[T], U]) → U¶ Applies a function to the contained value (if any), or computes a default (if not).
>>> k = 21 >>> >>> x = Some("foo") >>> x.map_or_else(lambda: 2 * k, len) 3 >>> x: Option[str] = None_() >>> x.map_or_else(lambda: 2 * k, len) 42
-
ok_or
(err: E) → patina.result.Result[~T, ~E][T, E]¶ Transforms the
Option[T]
into aResult[T, E]
, mappingSome(v)
toOk(v)
andNone_
toErr(err)
.Arguments passed to
ok_or
are eagerly evaluated; if you are passing the result of a function call, it is recommended to useok_or_else()
, which is lazily evaluated.>>> x = Some("foo") >>> x.ok_or(0) Ok('foo') >>> x: Option[str] = None_() >>> x.ok_or(0) Err(0)
-
ok_or_else
(err: Callable[[], E]) → patina.result.Result[~T, ~E][T, E]¶ Transforms the
Option[T]
into aResult[T, E]
, mappingSome(v)
toOk(v)
andNone_
toErr(err())
.>>> x = Some("foo") >>> x.ok_or_else(lambda: 0) Ok('foo') >>> x: Option[str] = None_() >>> x.ok_or_else(lambda: 0) Err(0)
-
iter
() → Iterator[T]¶ Returns an iterator over the possibly contained value.
>>> x = Some(4) >>> next(x.iter()) 4 >>> x: Option[int] = None_() >>> next(x.iter()) Traceback (most recent call last): ... StopIteration
-
__iter__
()¶ Returns an iterator over the possibly contained value.
>>> x = Some(4) >>> next(iter(x)) 4 >>> x: Option[int] = None_() >>> next(iter(x)) Traceback (most recent call last): ... StopIteration
-
and_
(optb: patina.option.Option[~U][U]) → patina.option.Option[~U][U]¶ Returns
None_
if the option isNone_
, otherwise returnsoptb
.>>> x = Some(2) >>> y: Option[str] = None_() >>> x.and_(y) None_ >>> x: Option[int] = None_() >>> y = Some("foo") >>> x.and_(y) None_ >>> x = Some(2) >>> y = Some("foo") >>> x.and_(y) Some('foo') >>> x: Option[int] = None_() >>> y: Option[str] = None_() >>> x.and_(y) None_
-
and_then
(f: Callable[[T], Option[U]]) → patina.option.Option[~U][U]¶ Returns
None_
if the option isNone_
, otherwise callsf
with the wrapped value and returns the result.Some languages call this operation flatmap.
>>> def sq(x: int) -> Option[int]: return Some(x * x) ... >>> def nope(_: 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_[int]().and_then(sq).and_then(sq) None_
-
filter
(predicate: Callable[[T], bool]) → patina.option.Option[~T][T]¶ Returns
None_
if the option isNone_
, otherwise callspredicate
with the wrapped value and returns:Some(t)
ifpredicate
returnsTrue
(wheret
is the wrapped value, andNone_
ifpredicate
returnsFalse
.
This function works similar to
filter()
. You can imagine theOption[T]
being an iterator over one or zero elements.filter()
lets you decide which elements to keep.>>> def is_even(n: int) -> bool: return n % 2 == 0 ... >>> None_[int]().filter(is_even) None_ >>> Some(3).filter(is_even) None_ >>> Some(4).filter(is_even) Some(4)
-
or_
(optb: patina.option.Option[~T][T]) → patina.option.Option[~T][T]¶ Returns the option if it contains a value, otherwise returns
optb
.Arguments passed to
or
are eagerly evaluated; if you are passing the result of a function call, it is recommended to useor_else()
, which is lazily evaluated.>>> x = Some(2) >>> y: Option[int] = None_() >>> x.or_(y) Some(2) >>> x: Option[int] = None_() >>> y = Some(100) >>> x.or_(y) Some(100) >>> x = Some(2) >>> y = Some(100) >>> x.or_(y) Some(2) >>> x: Option[int] = None_() >>> y: Option[int] = None_() >>> x.or_(y) None_
-
or_else
(f: Callable[[], Option[T]]) → patina.option.Option[~T][T]¶ Returns the option if it contains a value, otherwise calls
f
and returns the result.>>> def nobody() -> Option[str]: return None_() ... >>> def vikings() -> Option[str]: return Some("vikings") ... >>> Some("barbarians").or_else(vikings) Some('barbarians') >>> None_[str]().or_else(vikings) Some('vikings') >>> None_[str]().or_else(nobody) None_
-
xor
(optb: patina.option.Option[~T][T]) → patina.option.Option[~T][T]¶ Returns
Some
if exactly one ofself
,optb
isSome
, otherwise returnsNone_
.>>> x = Some(2) >>> y: Option[int] = None_() >>> x.xor(y) Some(2) >>> x: Option[int] = None_() >>> y = Some(2) >>> x.xor(y) Some(2) >>> x = Some(2) >>> y = Some(2) >>> x.xor(y) None_ >>> x: Option[int] = None_() >>> y: Option[int] = None_() >>> x.xor(y) None_
-
get_or_insert
(v: T) → patina.ref.Ref[~T][T]¶ Inserts
v
into the option if it isNone_
, then returns a reference to the contained value.>>> x: Option[int] = None_() >>> y = x.get_or_insert(5) >>> y.get() 5 >>> y.set(7) >>> x Some(7)
-
get_or_insert_with
(f: Callable[[], T]) → patina.ref.Ref[~T][T]¶ Inserts a value computed from
f
into the option if it isNone_
, then returns a reference to the contained value.>>> x: Option[int] = None_() >>> y = x.get_or_insert_with(lambda: 5) >>> y.get() 5 >>> y.set(7) >>> x Some(7)
-
take
() → patina.option.Option[~T][T]¶ Takes the value out of the option, leaving a
None_
in its place.>>> x = Some(2) >>> y = x.take() >>> x None_ >>> y Some(2) >>> x: Option[int] = None_() >>> y = x.take() >>> x None_ >>> y None_
-
replace
(value: T) → patina.option.Option[~T][T]¶ Replaces the actual value in the option by the value given in parameter, returning the old value if present, leaving a
Some
in its place without deinitializing either one.>>> x = Some(2) >>> old = x.replace(5) >>> x Some(5) >>> old Some(2) >>> x = None_[int]() >>> old = x.replace(3) >>> x Some(3) >>> old None_
-
zip
(other: patina.option.Option[~U][U]) → patina.option.Option[typing.Tuple[~T, ~U]][Tuple[T, U]]¶ Zips
self
with anotherOption
.If
self
isSome(s)
andother
isSome(o)
, this method returnsSome((s, o))
. Otherwise,None_
is returned.>>> x = Some(1) >>> y = Some("hi") >>> z = None_[int]() >>> x.zip(y) Some((1, 'hi')) >>> x.zip(z) None_
-
classmethod
from_optional
(opt: Optional[T]) → patina.option.Option[~T][T]¶ Get an
Option[T]
from anOptional[T]
.If
opt
isNone
, returnNone_()
, otherwise returnSome(obj)
. This does not come from Rust’s API.>>> from typing import Optional >>> x: Optional[int] = None >>> Option.from_optional(x) None_ >>> x: Optional[int] = 42 >>> Option.from_optional(x) Some(42)
-
into_optional
() → Optional[T]¶ Get a typing.Optional[T] from an
Option[T]
.Returns
None
ifself
isNone_()
, otherwise returns the contained value.>>> from typing import Optional >>> x: Optional[int] = None >>> opt = Option.from_optional(x) >>> opt None_ >>> opt.into_optional() >>> assert x is opt.into_optional() >>> >>> x = 3 >>> opt = Option.from_optional(x) >>> opt Some(3) >>> opt.into_optional() 3 >>> assert x is opt.into_optional()
-
__weakref__
¶ list of weak references to the object (if defined)
-