Improve motivating example for Maybe
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 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.
@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...