Browse Source

More subtle SafeCompare()

If all operands to a comparison are None, the comparison function should not
be called; the two operands are equal - they're all None ...

So SafeCompare() now only executes the comparison function if none of the
operands are None and returns True if all operands are None, False if some
of the operands are None.
haavee 8 months ago
1 changed files with 12 additions and 2 deletions
  1. +12

+ 12
- 2 View File

@@ -92,8 +92,18 @@ sorteable_none = choice(is_none, const(Niets), identity)
# exception FFS.
# So we just have to roll our own "is the value None present in this list/tuple?"
contains_none = compose(any, Map(is_none))
SafeCompare = lambda f: lambda *args: False if contains_none(args) else f(*args)
# But that is not enough - if all operands to the operation are None they should compare equal as well
# but without having to call the operator

# index into the comparison table is (any, all).
# we only need to check for conditions where
# any == True and discriminate between all/some.
# If any == False this implies all == False (all == True is impossible in this case)
comp_table_ = {(True, True) : const(True), # all = True -> all operands None -> .EQ.
(True, False): const(False)} # all = False -> some operands None -> .NE.

any_all = compose(pam(any, all), Map(is_none))
SafeCompare = lambda f: lambda *args: comp_table_.get( any_all(args), f)(*args)
SumAttr = lambda a: lambda o0, o1: setattr(o0, a, getattr(o0, a)+getattr(o1, a))
AppendAttr = lambda a: lambda o0, o1: setattr(o0, a, getattr(o0, a).append(getattr(o1, a)))
FloatEq = SafeCompare(lambda l, r: abs(l-r)<1e-3)