On 9/24/2018 3:46 AM, Marko Ristin-Kaufmann wrote:
I am responding to your request "Please do point me to what is not obvious to you". I think some of your claims are not only not obvious, but are wrong. I have read some (probably less than half) of the responses and avoid saying what I know others have covered adequately.
A mathematical function is defined or specified by a input domain, output range, and a mapping from inputs to outputs. The mapping can be defined either by an explicit listing of input-output pairs or by a rule specifying either a) the process, what is done to inputs to produce outputs or, b) the result, how the output relates to the input.
defines contracts as "precise (legally unambiguous) specifications" (5.2 Business Contracting/Sub-contracting Metaphor) It is not obvious to me that the metaphor of contracts adds anything worthwhile to the idea of 'function'.
1. Only a small sliver of human interactions are governed by formal legal contracts read, understood, and agreed to by both (all) parties.
2. The idealized definition is naive in practice. Most legal contracts, unlike the example in the link article, are written in language that most people cannot read. Many contracts are imprecise and legally ambiguous, which is why we have contract dispute courts. And even then, the expense means that most people who feel violated in a transaction do not use courts.
Post-conditions specify a function by result. I claim that this is not always sensible. I said above that functions may be specified by process rather than result. Ironically, the contract metaphor reinforces my claim. Many contracts, such as in teaching and medicine, only specify process and explicitly disclaim any particular result of concern to the client.
b)//If you write contracts in text, they will become stale over time
Not true for good docstrings. We very seldom change the essential meaning of public functions.
How has "Return the sine of x (measured in radians).", for math.sin, become stale? Why would it ever? What formal executable post condition would help someone who does not understand 'sine', or 'sine of x'? The function is only useful for someone who either understands 'sine' or is copying a formula written elsewhere without needing to understand it.
Or consider "Stable sort *IN PLACE*." for list.sort. A formal executable post-condition for this *can* be written. But for someone who understands the words 'stable', 'sort', and 'in place', this compact English post condition is much more readable than any formal version could be. More over, that addition of 'stable', when we were ready to do so, did not make "Sort *IN PLACE*" stale in any sense of being wrong.
I said above that functions definitions and contracts can specify the process rather than the result. For functions, the code is the process, and the code may then be the specification and the contract. For instance,
def append_first(seq): "Append seq to seq."
So seq must have a first element accessed as seq and an append method that accepts the first element as an argument. One might guess the minimal body.
The pre-condition here is that the return value can be calculated as specified. Whenever this is true, python is already testing pre-conditions, as efficiently as possible. We could elaborate the body as
try: return seq.append(seq) except Exception as e: raise ValueError('raised ' + repr(e))
and add 'Raise ValueError with explanation on bad input' to the doc string.
If the domain were restricted to lists, we could write a post-condition, and use that in a list-based unittest. However, it likely be less readable than the docstring, and would execute in O(n) time (for an O(1) function). The latter is acceptable for unittests, which will use short tests, but not for production. But with duck-typing, no post condition is possible. Neither is a generic unittest. The code *is* the contract. This is generally true of duck-typed Python code.