On Tue, Feb 19, 2019 at 11:05:55PM +0200, Miikka Salminen wrote: > Hi! > > To help automatic document generators and static type checkers reason more > about the code, the possible side-effects and raised exceptions could also > be annotated in a standardized way.
This is Python. Nearly everything could have side-effects or raise exceptions *wink* Despite the wink, I am actually serious. I fear that this is not compatible with duck-typing. Take this simple example: @raises(TypeError) def maximum(values:Iterable)->Any: it = iter(values) try: biggest = next(it) except StopIteration: return None for x in it: if x > biggest: biggest = x return x But in fact this code can raise anything, or have side-effects, since it calls x.__gt__ and that method could do anything. So our decoration about raising TypeError is misleading if you read it as "this is the only exception the function can raise". You should read it as "this promises to sometimes raise TypeError, but could raise any other exception as well". This pretty much shows that the idea of checked exceptions doesn't go well with Python's duck-typing. And I note that in Java, where the idea of checked exceptions originated, it turned out to be full of problems and a very bad idea. Here is your example: > In [3]: @raises(ValueError) > ...: def hello_if_5(x: int) -> None: > ...: if x != 5: > ...: raise ValueError("number other than 5 given") > ...: print("Hello!") In this *trivial* function, we can reason that there are no other possible exceptions (unless ValueError or print are monkey-patched or shadowed). But how many of your functions are really that simple? I would expect very few. For the vast majority of cases, any time you decorate a non-trivial function with "raises(X)", it needs to be read as "can raise X, or any other exception". And similarly with annotating functions for side-effects. I expect that most functions need to be read as "may have side-effects" even if annotated as side-effect free. So the promises made will nearly always be incredibly weak: - raises(A) means "may raise A, or any other unexpected exception" - sideeffects(True) means "may have expected side-effects" - sideeffects(False) means "may have unexpected side-effects" I don't think there is much value in a static checker trying to reason about either. (And the experience of Java tells us that checking exceptions is a bad idea even when enforced by the compiler.) If I'm right, then adding support for this to the std lib is unnecessary. But I could be wrong, and I encourage static checkers to experiment. To do so, they don't need support from the std lib. They can provide their own decorator, or use a comment: # raises ValueError, TypeError # +sideeffects def spam(): ... -- Steve _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/