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

Exceptions? #5

Open
tpgillam opened this issue Jan 21, 2025 · 5 comments
Open

Exceptions? #5

tpgillam opened this issue Jan 21, 2025 · 5 comments

Comments

@tpgillam
Copy link
Owner

The current early prototype uses error value types rather than exceptions.

The ergonomics of this, unfortunately, are not great, because Python has no equivalent to rust's ? operator which would allow immediately returning from the current value with any error value encountered.

This adds boilerplate in encode and decode, including in the coders that users will write (since they may have to encode attributes of a type).

Exceptions are "easier", at the expense of harder-to-follow control flow in error cases.

@Rupt
Copy link
Collaborator

Rupt commented Jan 21, 2025

if isinstance(payload, EncodeError):
    return payload

is simple, explicit, and unambiguous.

@Rupt
Copy link
Collaborator

Rupt commented Jan 21, 2025

More boilerplate, but one could consider a rust-like unwrap setup, where all possible return types have an unwrap method that users can call if they want to raise on error.

Half-baked sketch:

@dataclasses.dataclass(frozen=True, slots=True)
class Error:
    msg: str

    def unwrap() -> Never:
        raise ValueError(self.msg)


@dataclasses.dataclass(frozen=True, slots=True)
class Success[T]:
    value: T

    def unwrap() -> T:
        return self.value


def encode_to_document(obj: object, fmt: SerialisationFormat) -> Error | Success[Document]:
    ...

@tpgillam
Copy link
Owner Author

tpgillam commented Jan 21, 2025

Unfortunately you get the explosion:

# hypothetical
return [encode(x, fmt) for x in some_list]

# current
res: list[JsonType] = []
for x in some_list:
    tmp = encode(x, fmt)
    if isinstance(tmp, EncodeError):
        return tmp
    res.append(tmp)
return res

but it's also true that the comprehension case won't be encountered by downstream users, since if they have an attribute they want to encode that is a list, then they can can rely on encode(self.some_list_attribute, fmt) doing the iteration.

edit: I don't really care about boilerplate at all within this library. So on those grounds error types are actually not so bad.

@tpgillam
Copy link
Owner Author

I think unwrap is a nice feature we could provide to let downstream users use exceptions if they want to. Neat!

@tpgillam
Copy link
Owner Author

So it seems like someone made a library roughly along these lines.
But it's recently become unmaintained, and there are some grumbles from maintainers about it not being a style that suits python well: rustedpy/result#201 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants