Wrapping Python
Going from the imperative paradigm of procedures and raising Exception (among other effects results) to the functional “handling in a value” style can be tedious, both to lift results into Xresult and then to process multiple Xresult alltogether. XFP ensures a smooth interface between plain Python and functional Python.
Xopt lifting
XFP provides a simple and straightforward method to infer the branch of an optional value while creating a result.
from xfp import Xopt, Xresult
python_optional: None | int = None
maybe: Xresult[None, int] = Xopt.from_optional(python_optional)
The from_optional
constructor allows automatic result creation, which will be a LEFT when the python optional is None and a RIGHT otherwise.
Xresults lifting
Xtry
Xtry provides two ways of switching from functions that raises to functions that returns Xresult. You will use either one of them depending on if you are :
-
Integrating with a third-party API :
import pandas as pd from xfp import Xtry, Xresult tried_df: Xresult[Exception, pd.DataFrame] = Xtry.from_unsafe(lambda: pd.read_csv("may_break_file"))
-
Dealing with legacy code written imperative-style :
from xfp import Xtry, Xresult @Xtry.safed def that_can_raise(i: int) -> str: if i > 0: return str(i) else: raise Exception("an Exception") result: Xresult[Exception, str] = that_can_raise(3)
the Xtry.from_unsafe
feature relies on the unparametrized lambda to lazily evaluate the code given to it. It allows to delegate its execution to the from_unsafe
wrapper, which ensures catching any non fatal exception that can be thrown.
The Xtry.safed
decorator, on the other side, automatically wrap its subject inside a from_unsafe
on call, effectivelly changing its signature to an Xresult.
While Xtry.safed
can look appealing by removing some boilerplate on your handcrafted function, the best practice remains to explicitely returns Xtry.Success
and Xtry.Failure
to eliminate unnecessary confusion over both the code readability and the function signature.