dry-python / returns

Make your functions return something meaningful, typed, and safe!
https://returns.rtfd.io
BSD 2-Clause "Simplified" License
3.55k stars 116 forks source link

support for Python's container interfaces #1091

Open ariebovenberg opened 3 years ago

ariebovenberg commented 3 years ago

related: #874, #592

Python has a rich set of container interfaces, like __iter__, __len__, __contains__, and others.

could we treat Maybe as a collection (i.e. one containing 0 or 1 items)? It may seem weird, but it has precedent. In Rust, Option implements iteration and other collection-like traits as well.

...but why?

>>> def parse_int(s: str) -> Maybe[int]: ...

>>> # easier flattening with `__iter__`
>>> list(chain.from_iterable(map(parse_int, 'a45bf'))))
[4, 5]

>>> # truthiness with `__bool__`
>>> if parse_int(mystr):
...     print('a valid int!')

>>> # checking contents with `__contains__`
>>> if 5 in parse_int(mystr):
...     print('number five detected!')

>>> # not strictly collection-related but still nice: __or__ and __and__
>>> Some(5) & Some(9)
Some(9)
>>> Some(9) & Nothing
Nothing
>>> Nothing & Some(8)
Nothing
>>> Some(5) | Some(9)
Some(5)
>>> Some(9) | Nothing
Some(9)
>>> Nothing | Some(8)
Some(8)
>>> Nothing | Nothing
Nothing

>>> # if you want to go crazy: use __getitem__ to implement Sequence
>>> Some(6)[0]
6
>>> Some(8)[8]
Exception: IndexError
>>> Nothing[0]
Exception: IndexError
...
>>> Some(6)[:]
Some(6)
>>> Some(2)[:9:4]
Some(2)
>>> Some(7)[2:]
Nothing
>>> Nothing[:]
Nothing
>>> Nothing[2:9:5]
Nothing

I'm sure you have some opinion on this, but couldn't find it in the issues so far... πŸ‘€

sobolevn commented 3 years ago

Good idea! But, we are blocked right now because of #392 I don't know which methods it will require.

ariebovenberg commented 2 years ago

Interesting!

Note though that once you abuse one of the container interfaces (iter, getitem, contains, etc.), the others are pretty much off the table as well (otherwise you get a really wonky API)

I'm eager to see what the outcome is πŸ‘€