Skip to content

Instantly share code, notes, and snippets.

@veber-alex
Created May 15, 2021 20:06
Show Gist options
  • Save veber-alex/a4ada60012b270db0f0bbf481bbe4b28 to your computer and use it in GitHub Desktop.
Save veber-alex/a4ada60012b270db0f0bbf481bbe4b28 to your computer and use it in GitHub Desktop.
Python Result type simulating Rust's Result enum.
from typing import Generic, Optional, TypeVar
from abc import ABC, abstractmethod
from dataclasses import dataclass
T = TypeVar('T')
E = TypeVar('E')
class Result(Generic[T, E], ABC):
@abstractmethod
def ok(self) -> Optional[T]:
pass
@abstractmethod
def err(self) -> Optional[E]:
pass
@dataclass
class Ok(Result[T, E]):
value: T
def ok(self) -> Optional[T]:
return self.value
def err(self) -> Optional[E]:
return None
@dataclass
class Err(Result[T, E]):
error: E
def ok(self) -> Optional[T]:
return None
def err(self) -> Optional[E]:
return self.error
def test(x: int) -> Result[int, str]:
if x > 10:
return Ok(x)
else:
return Err("error")
def main():
if result := test(20).ok(): # same as `if let Ok(result) = test(20)` in Rust
print(result + 42) # the type checker knows result is `int` here
# New in 3.10
match test(8):
case Ok(result):
print(result + 42)
case Err(e):
print(e + " :(")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment