returns icon indicating copy to clipboard operation
returns copied to clipboard

Improve motivating example for Maybe

Open dan-sel opened this issue 5 years ago • 2 comments

The current example motivating the use of Maybe is somewhat misleading because it solves a made-up problem:

Alleged original "python" code:

if user is not None:
     balance = user.get_balance()
     if balance is not None:
         credit = balance.credit_amount()
         if credit is not None and credit > 0:
             discount_program = choose_discount(credit)

Alleged "better" solution using Maybe:

discount_program: Maybe['DiscountProgram'] = Maybe.from_optional(
    user,
).bind_optional(  # This won't be called if `user is None`
    lambda real_user: real_user.get_balance(),
).bind_optional(  # This won't be called if `real_user.get_balance()` is None
    lambda balance: balance.credit_amount(),
).bind_optional(  # And so on!
    lambda credit: choose_discount(credit) if credit > 0 else None,
)

Usual python code solving this exact problem:

try:
    discount_program = choose_discount(user.get_balance().credit_amount())
except AttributeError:
    pass

The example is based on the very bad habit of signaling errors by return values, e.g. returning None.

No sane (python) developer would write a function that returns None in case of an error unless there is good reason for it, it is properly documented and returning None immediately and unambiguously tells the caller what went wrong. When exceptions occur, exceptions should be raised.

For example, credit_amount() returning None conveys no meaning at all. No credit? Credit amount == 0? Credit amount < 0? Raccoons taking over the world?

And even if one had to use flawed 3rd party code like this, there is a shorter and more concise version to handle this without Maybe.

I believe there is a legitimate use case for Maybe, but this is not it.

dan-sel avatar Dec 24 '20 00:12 dan-sel

@dan-sel thank you for your feedback!

I have heard several opinions that the current Maybe example is not so great. I and seem to agree. I would think about other possible examples here. Any suggestions are welcome.

In my practice I don't use Maybe that much, because I prefer to use Result that covers almost all cases.

sobolevn avatar Dec 24 '20 08:12 sobolevn

@dan-sel the provided "pythonic" solution doesn't actually solves the problem, although it looks cool!

It catches all possible AttributeErrors but with multiple calls under single 'try' you can't really know from which exact call you got an AttributeError. So you can't do any certain recover steps.

After all i agree that provided pipeline in documentation doesn't look inspiring or 'much better' than original 'problematic' code. it reminds me of most unreadable JS code fragments...

Eduard-gan avatar May 13 '22 13:05 Eduard-gan