-
Result & ResultEpython/returns 2022. 9. 4. 21:37
https://returns.readthedocs.io/en/latest/pages/result.html
- scala Either 와 비슷한듯
- error 를 Exception 으로 고정해 scala Try 처럼 사용해도 좋을 듯, ResultE[T] = Result[T, Exception]
- Result.do 와 pipe 도 알아두자 (flow 대신에 Result.do 를 사용하자?)
from typing import Callable from returns.pipeline import flow, pipe from returns.pointfree import bind from returns.result import Result, Success, Failure, ResultE x: ResultE[int] = Success(2) # x: Result[int, Exception] = Success(2) y: ResultE[int] = Success(3) # y: Result[int, Exception] = Success(3) def sum_of(x: int, y: int) -> int: return x + y # scala 에서의 for-comprehension ? z = Result.do( a + b # sum_of(a, b) 로도 표현 가능 for a in x for b in y ) # Success(5) ############################################################# def f(x: int) -> ResultE[int]: return Success(x + 1) def g(x: int) -> ResultE[int]: return Success(x * 2) # 시작 값으로 computation (이것 보다는 아래의 Result.do 를 쓰는 것이 좋아 보임) flow( 1, # instance f, # function bind(g) # function ) # Success(4) # 위의 flow 를 Result.do 로 표현 Result.do( y for x in f(1) for y in g(x) ) # Success(4) # function composition: 시작 값이 없이 function composition h: Callable[[int], ResultE[int]] = pipe( f, bind(g) ) h(1) # Success(4) ############################################################# def recover(e: Exception) -> int: return 123 def recover_with(e: Exception) -> ResultE[int]: return Success(456) def find_user(id: int) -> ResultE[int]: if id == 1: return Success(id + 100) else: return Failure(ValueError("invalid value")) find_user(1).alt(recover) # 101 find_user(2).alt(recover) # 123 find_user(1).lash(recover_with) # 101 find_user(2).lash(recover_with) # 456
Result + Maybe
from returns.maybe import Maybe, Some from returns.pipeline import is_successful from returns.result import Success, ResultE, Failure, Result # maybe: Maybe[int] = Some(3) maybe: Maybe[int] = Maybe.empty # result: ResultE[int] = Success(1) result: ResultE[int] = Failure(ValueError) z: Maybe[int] | ResultE[int] = Result.do( x + y for x in maybe for y in result ) # 방법 1 v: int = z.value_or(9) print(v) # 방법 2 if is_successful(z): v = z.unwrap() print(v) else: print('Error') # 방법 3 match z: case Some(v) | Success(v): print(v) case Maybe.empty: print('Maybe Error') case Failure(e): print('Result Error')
Result v.s Maybe
from returns.converters import maybe_to_result, result_to_maybe from returns.maybe import Maybe, Some from returns.pipeline import is_successful from returns.result import Result, Success, ResultE x: ResultE[int] = Success(2) a: Maybe[int] = result_to_maybe(x) b: Maybe[int] = Some(3) y: Result[int, None] = maybe_to_result(b) c: Maybe[int] = Nothing z: ResultE[int] = maybe_to_result(c, Exception('error')) # Failure("error") z.failure() # Get failed value or raise exception. is_successful(b) is_successful(y)
@safe
from returns.result import Success, Failure, safe # Will convert type to: Callable[[int], ResultE[float]] @safe def divide(n: int, m: int) -> float: return n / m match divide(1, 0): case Success(10): print('Result is "10"') case Success(value): print(f'result={value}') case Failure(ZeroDivisionError()): print('"ZeroDivisionError" was raised') case Failure(_): print('The division was a failure')
safe 직접 호출
from returns.result import ResultE, safe def divide(n: int, m: int) -> float: return n / m z: ResultE[float] = safe(divide)(1, 0) print(z) # <Failure: division by zero>
'python > returns' 카테고리의 다른 글
IO & IOResult (0) 2022.09.04 Maybe (0) 2022.09.04