3 ms·
A similar "framework", very robust and used in production systems, is dry-python's one[0][1]. The approach taken is a bit different I think, since they rely he
by hackandtrip 5y ago
A similar "framework", very robust and used in production systems, is dry-python's one[0][1].
The approach taken is a bit different I think, since they rely heavily on `mypy` plugins to reach type safety and functional constructs otherwise impossible to get, without runtime inspections.
0: https://github.com/dry-python https://github.com/dry-python
1: https://github.com/dry-python/returns https://github.com/dry-python/returns
- keithasaurus 5y agodry-python has a lot of cool stuff. I encourage people to check it out. Koda has a slightly different approach in that it's meant to be a little simpler than returns, and to work within Python's constraints.
- exdsq 5y agoAm I strange for disagreeing with the very first example of dry-python? They suggest the second version is "much better" than the first but I sort of hate it. 1 =================== user: Optional[User] discount_program: Optional['DiscountProgram'] = None 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) 2 =================== user: Optional[User] 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, )
- properdine 5y agoI agree with you that the second is less readable and less pythonic (feels more JS/Node-ish).
- chrischen 5y agoThe second example is a pretty standard monadic composition pipeline. In languages like Haskell or F# there can be special syntax to make it easier to read (do notation or computation expressions). However if you’ve never done it will be hard to read. It’s easy to read to someone who has the background, and it is easier to refactor and less error prone because the context of a nullable value (the if statement checks) is factored out from the core logic. So if the core logic needs to be changed it can be done so without touching the if statement checking for None.
- FreakLegion 5y agoEspecially given the first example is tailor-made for the walrus operator. if (balance := user.get_balance()) and (credit := balance.credit_amount()): discount_program = choose_discount(credit) (Omitting the credit > 0, and without getting into other fundamental issues with the implied design, since it's just a readme example.)