PEP 532: Rework De Morgan's Laws section

This commit is contained in:
Nick Coghlan 2016-12-12 16:03:39 +10:00
parent b171bc0f79
commit 65b178826a
1 changed files with 24 additions and 21 deletions

View File

@ -778,37 +778,40 @@ combination of ``not`` operations.
For ``and`` and ``or`` in Python, these invariants can be described as follows:: For ``and`` and ``or`` in Python, these invariants can be described as follows::
assert (A and B) == (not (not A or not B)) assert bool(A and B) == bool(not (not A or not B))
assert (A or B) == (not (not A and not B)) assert bool(A or B) == bool(not (not A and not B))
That is, if you take one of the operators, invert both operands, switch to the That is, if you take one of the operators, invert both operands, switch to the
other operator, and then invert the overall result, you'll get the same other operator, and then invert the overall result, you'll get the same
answer as you did from the original operator. (This may seem redundant, answer (in a boolean sense) as you did from the original operator. (This may
but in many situations it actually lets you eliminate double negatives and find seem redundant, but in many situations it actually lets you eliminate double
tautologically true or false subexpressions, thus reducing the overall negatives and find tautologically true or false subexpressions, thus reducing
expression size). the overall expression size).
For circuit breakers, defining a suitable invariant is complicated by the For circuit breakers, defining a suitable invariant is complicated by the
fact that they're designed to eliminate themselves from the expression result fact that they're often going to be designed to eliminate themselves from the
when they're short-circuited, which is an inherently asymmetric behaviour. expression result when they're short-circuited, which is an inherently
Accordingly, that inherent asymmetry needs to be corrected for when mapping asymmetric behaviour. Accordingly, that inherent asymmetry needs to be
De Morgan's Laws to the expected behaviour of symmetric circuit breakers. accounted for when mapping De Morgan's Laws to the expected behaviour of
symmetric circuit breakers.
One way this complication can be addressed is to wrap the operand that would
otherwise short-circuit in ``operator.true``, ensuring that when ``bool`` is
applied to the overall result, it uses the same definition of truth that was
used to decide which branch to evaluate, rather than applying ``bool`` directly
to the circuit breaker's input value.
Specifically, for the new short-circuiting operators, the following properties Specifically, for the new short-circuiting operators, the following properties
would be reasonably expected to hold for any well-behaved symmetric circuit would be reasonably expected to hold for any well-behaved symmetric circuit
breaker that implements all of ``__bool__``, ``__not__``, ``__then__``, and breaker that implements both ``__bool__`` and ``__not__``::
``__else__``:
cb_A = to_cb(A) assert bool(B if true(A)) == bool(not (true(not A) else not B))
cb_B = to_cb(B) assert bool(true(A) else B) == bool(not (not B if true(not A)))
assert (B if cb_A) is short_circuit(not (not cb_A else not cb_B))
assert (cb_A else B) is short_circuit(not (not cb_B if not cb_A))
Where ``to_cb`` returns a symmetric circuit breaker that produces the supplied Note the order of operations on the right hand side (applying ``true``
value when short-circuited, and ``short_circuit`` is defined as:: *after* inverting the input circuit breaker) - this ensures that an
assertion is actually being made about ``type(A).__not__``, rather than
def short_circuit(expr): merely being about the behaviour of ``type(true(A)).__not__``.
return expr if expr else expr
At the very least, ``types.CircuitBreaker`` instances would respect this At the very least, ``types.CircuitBreaker`` instances would respect this
logic, allowing existing boolean expression optimisations (like double logic, allowing existing boolean expression optimisations (like double