Well, /g/?
'''
Here are two different implementations of the OR operation
for Kleene's three-valued logic (possible values are True, False and Unknown).
Unknown is represented by None.
Examples:
or3(True, None) == True
or3(False, None) = None
The first implementation is more elegant,
but if you accidentally pass a Generator, it will produce the wrong result:
or3((_ for _ in [False, None]))) returns False (instead of None)
The second implementation works with generators and is probably faster.
But imagine this was a more complicated function
where the first approach would make it much more readable.
Which implementation would you pick in that case?
How would you make the first approach generator-proof?
Mypy doesn't raise a warning when passing a Generator to it (by default).
'''
def or3(ls: Collection[Union[bool, None]]) -> Union[bool, None]:
if any(ls): return True
if all(i == False for i in ls): return False
return None
def or3(ls: Iterable[Union[bool, None]]) -> Union[bool, None]:
unknown_flag = False
for v in ls:
if v: return True
if v is None: unknown_flag = True
if unknown_flag:
return None
return False