When Python Core Devlopers Fail Math History
I just love Raymond Hettingers talks, he's a superb educator (and pilot, and father, and python core developer). But here:
he got some things wrong a decade or so ago. So watch that talk up to about 00:15:30
There I think confusion reigned, and it is disappointing. I think it's an instance of python core developers failing math history. You should expect the subtraction to yield "c": -1 because "subtraction" is in our culture an arithmetical operation, an inverse to addition. What Knuth (characteristically verbosely) called "saturation subtraction" is just a very simple elementary operation a child might call "deletion" or "removal" --- exactly same meaning in common English. Not an inverse of addition. "Saturation subtraction" is an inverse of "creation", not of addition. So for Counters C - B
should be equivalent to C.subtract(B)
and the Python library should have a different operation,
C.remove(B)
So with,
>>> C
Counter({"a": 4, "c": 2, "b": 1, "z": 1, "t': 1})
>>> B
Counter({"a": 1, "b": 3, "c": 1, "t": 1, "z": 2})
we get,
>>> C - B
Counter({"a": 3, "c": 1}) # <--- the horror! It should be same as "decrement" intuitively.
>>> C.subtract(B)
>>> C
Counter({"a": 3, "c": 1, "b": -2, "t": 0, "z": -1}) # <--- fine.
So the infix subtract behaviour is a flaw IMHO. Those two results should be equivalent and we should have instead,
>>> C.remove(B)
Counter({'a': 3, 'c': 1})
Or at least: C.setminus(B)
instead of the counter-intuitive C - B
for the saturation subtraction, but since Counters are not sets I would vote against that method name. For two Set objects the infix " - " is of course behaving perfectly intuitively, {"cat", "dog"} - {"cat", "cat"}
should indeed give {"dog"}
which, it does, but the objects there are sets, and so all mathematicians know what'll happen, so no conflict with mathematical culture.
In the real world counters have gone negative since antiquity, since the earliest recorded writing, which were (if I recall) Sumerian records of credit/debt balance sheets of a sort. So I think Raymond got it wrong, Counters are not Sets, there is a relationship, but not that deep: every positively counted object is one in a set, but negative tallies count too, they are a "debt". It's a subtle relationship. When you subtract the Counters you subtract tallies, not the objects of each set. If you used my <Counter>.remove()
or <Counter>.setminus()
proposal then the name of the method is crystal clear, this time the operation is, by implication of English language, on the objects, not the tallies.