Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add safe_call, Expected, rename of to call #691

Closed
evhub opened this issue Dec 6, 2022 · 4 comments
Closed

Add safe_call, Expected, rename of to call #691

evhub opened this issue Dec 6, 2022 · 4 comments

Comments

@evhub
Copy link
Owner

evhub commented Dec 6, 2022

Should keep of as a deprecated alias for call that's removed in --strict compilation.

Definition of safe_call:

def safe_call(_f, *args, **kwargs):
    try:
        return _f(*args, **kwargs), None
    except Exception as err:
        return None, err

safe_call is useful for making long pipelines / point-free programming with exceptions.

@evhub evhub added the feature label Dec 6, 2022
@evhub evhub added this to the v2.1.2 milestone Dec 6, 2022
@evhub
Copy link
Owner Author

evhub commented Dec 6, 2022

Actually, maybe a better definition so you can continue the pipeline with fmap:

data Left[E <: Exception](error: E):
    def __fmap__(self, _) = self
data Right[T](result: T)
type Either[T] = Left | Right[T]
def safe_call(_f, *args, **kwargs):
    try:
        return Right(_f(*args, **kwargs))
    except Exception as err:
        return Left(err)

@evhub
Copy link
Owner Author

evhub commented Dec 6, 2022

maybe even better, to mimic the original tuple definition if you want to use it that way too:

data _safe_call_result[T](result: T?, error: Exception? = None):
    def __fmap__(self, func) = self if self.error is not None else Result(func(self.result))
    def __bool__(self) = self.error is None
def safe_call(_f, *args, **kwargs):
    try:
        return _safe_call_result(_f(*args, **kwargs))
    except Exception as err:
        return _safe_call_result(None, err)

@evhub
Copy link
Owner Author

evhub commented Dec 6, 2022

Maybe also provide _safe_call_result as a built-in—Either is a bit weird as a name, though, so probably go with Expected.

@evhub evhub changed the title Rename of to call, add safe_call Add safe_call, Expected, rename of to call Dec 6, 2022
evhub added a commit that referenced this issue Dec 6, 2022
@evhub
Copy link
Owner Author

evhub commented Dec 7, 2022

Final definition of Expected:

data Expected[T](result: T?, error: Exception?):
    def __new__(cls, result: T?=None, error: Exception?=None) -> Expected[T]:
        if result is not None and error is not None:
            raise ValueError("Expected cannot have both a result and an error")
        return makedata(cls, result, error)
    def __bool__(self) -> bool:
        return self.error is None
    def __fmap__[U](self, func: T -> U) -> Expected[U]:
        return self.__class__(func(self.result)) if self else self

@evhub evhub added the resolved label Dec 7, 2022
@evhub evhub closed this as completed Dec 7, 2022
evhub added a commit that referenced this issue Dec 25, 2022
evhub added a commit that referenced this issue Dec 25, 2022
evhub added a commit that referenced this issue Dec 25, 2022
@evhub evhub mentioned this issue Dec 28, 2022
evhub added a commit that referenced this issue Dec 30, 2022
evhub added a commit that referenced this issue Dec 30, 2022
evhub added a commit that referenced this issue Dec 30, 2022
evhub added a commit that referenced this issue Dec 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant