On Friday, May 1, 2020 at 1:30:17 PM UTC-4, vitalije wrote:
>
> As an example of the elegant code you can look at the returns 
> <https://returns.readthedocs.io/en/latest/> package. Quite often in Leo 
> None is used either as a return value from a function or as an argument to 
> the function. Just look at the examples in the *returns* documentaion how 
> using some other way to represent missing value simplifies and beautifies 
> the code.
>
> if user is not None:
>      balance = user.get_balance()
>      if balance is not None:
>          balance_credit = balance.credit_amount()
>          if balance_credit is not None and balance_credit > 0:
>              can_buy_stuff = True
> else:
>     can_buy_stuff = False
>
> # or using returns ...
> def get_balance(user):
>     return user.get_balance()
> def credit_amount(balance):
>     return balance.credit_amount()
> def is_positive(x):
>     return x > 0
>
> pipeline = pipe(
>     get_balance,
>     credit_amount,
>     is_positive,
> )
> can_buy_stuff = Maybe.from_value(user).map(pipeline)
>
> Look how beutifully and how easy it is to compose pure functions in the 
> pipeline and then mapping it to the Maybe value. And how nested and 
> unreadable code becomes when you have to do with possible None values. Leo 
> has many places where this pattern can be applied.
>
> How easy it would be to test this function. There is no place for bugs to 
> hide.
>

I almost hate to get into this, because it goes to show that everyone has a 
different notion of elegance and readability.  But I'm going to give you my 
reaction to your example here.  I only do this to highlight how it won't be 
so easy to replace the GUI code with something that many other people will 
want to deal with.

Your last line 

can_buy_stuff = Maybe.from_value(user).map(pipeline)

is almost opaque to me.  map tends to be hard to understand - that's why 
Python has mostly replaced it with list comprehensions - and I don't know 
what Maybe or from_value are supposed to be.  Also, the names don't work 
together consistently.  get_balance is clearly a verb, is_positive is a 
condition or test, and credit_balance is a noun. IMO, they don't belong 
together in a pipeline as if they were the same kind of thing.  

So I really don't like the way you have constructed things here.  In 
addition is not as error free as you imagine because the same edge cases 
still exist in the three functions.  So you are actually making some errors 
harder to detect.   I'd rather see a fluent style, or even a simplification 
of the original, maybe something like this:

can_buy_stuff = False
if user:
   # get_balance() always returns a balance object, creating one with 0 
credit if necessary
   credit = user.get_balance().credit_amount()
   can_buy_stuff = credit > 0

Or maybe something like this, which appeals more to me and seems more clear 
and self documenting than your pipeline:

# user must always have a balance, and balance must always have a credit
can_buy_stuff = user and user.balance.credit > 0

The guarantee of having balance and credit could be established at object 
creation.

Anyway, I'm sure there is lots of scope for more elegance in Leo's code, 
but there is more than one way.  It will take quite some thought.  I know 
that you have put a lot into your various experiments, I'm not trying to 
minimize that.  But maybe some new capability could be better implemented 
by applying your lessons, instead of a major re-write of the core all at 
once.

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/aac0c2da-e85c-4263-8b5b-5693dec8b49e%40googlegroups.com.

Reply via email to